[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 1.7.55. CORE-10536
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 22 Nov 2015 15:58:59 +0000 (15:58 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 22 Nov 2015 15:58:59 +0000 (15:58 +0000)
svn path=/trunk/; revision=70033

51 files changed:
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/vertexdeclaration.c
reactos/dll/directx/wine/d3d8/volume.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/vertexdeclaration.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/main.c
reactos/dll/directx/wine/ddraw/surface.c
reactos/dll/directx/wine/wined3d/arb_program_shader.c
reactos/dll/directx/wine/wined3d/ati_fragment_shader.c
reactos/dll/directx/wine/wined3d/buffer.c
reactos/dll/directx/wine/wined3d/context.c
reactos/dll/directx/wine/wined3d/cs.c
reactos/dll/directx/wine/wined3d/device.c
reactos/dll/directx/wine/wined3d/directx.c
reactos/dll/directx/wine/wined3d/drawprim.c
reactos/dll/directx/wine/wined3d/gl_compat.c
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c
reactos/dll/directx/wine/wined3d/palette.c
reactos/dll/directx/wine/wined3d/query.c
reactos/dll/directx/wine/wined3d/resource.c
reactos/dll/directx/wine/wined3d/sampler.c
reactos/dll/directx/wine/wined3d/shader.c
reactos/dll/directx/wine/wined3d/shader_sm1.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_private.h
reactos/include/psdk/d3d9.h
reactos/include/reactos/wine/wined3d.h
reactos/media/doc/README.WINE

index 6d79917..7d8a487 100644 (file)
@@ -185,6 +185,10 @@ struct d3d8_device
     LONG device_state;
     /* Avoids recursion with nested ReleaseRef to 0 */
     BOOL                    inDestruction;
+
+    /* The d3d8 API supports only one implicit swapchain (no D3DCREATE_ADAPTERGROUP_DEVICE,
+     * no GetSwapchain, GetBackBuffer doesn't accept a swapchain number). */
+    struct d3d8_swapchain   *implicit_swapchain;
 };
 
 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
@@ -213,12 +217,13 @@ struct d3d8_volume
 {
     IDirect3DVolume8 IDirect3DVolume8_iface;
     struct d3d8_resource resource;
-    struct wined3d_volume *wined3d_volume;
+    struct wined3d_texture *wined3d_texture;
+    unsigned int sub_resource_idx;
     struct d3d8_texture *texture;
 };
 
-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;
+void volume_init(struct d3d8_volume *volume, struct wined3d_texture *wined3d_texture,
+        unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d8_swapchain
 {
@@ -235,7 +240,8 @@ struct d3d8_surface
 {
     IDirect3DSurface8 IDirect3DSurface8_iface;
     struct d3d8_resource resource;
-    struct wined3d_surface *wined3d_surface;
+    struct wined3d_texture *wined3d_texture;
+    unsigned int sub_resource_idx;
     struct list rtv_entry;
     struct wined3d_rendertarget_view *wined3d_rtv;
     IDirect3DDevice8 *parent_device;
@@ -244,8 +250,8 @@ struct d3d8_surface
 };
 
 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;
+void surface_init(struct d3d8_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+        const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
 
 struct d3d8_vertexbuffer
index 0d02446..e8ec743 100644 (file)
@@ -175,9 +175,23 @@ static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS
     present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval;
 }
 
-static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
+static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
         const D3DPRESENT_PARAMETERS *present_parameters)
 {
+    if (!present_parameters->SwapEffect || present_parameters->SwapEffect > D3DSWAPEFFECT_COPY_VSYNC)
+    {
+        WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
+        return FALSE;
+    }
+    if (present_parameters->BackBufferCount > 3
+            || ((present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
+            || present_parameters->SwapEffect == D3DSWAPEFFECT_COPY_VSYNC)
+            && present_parameters->BackBufferCount > 1))
+    {
+        WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
+        return FALSE;
+    }
+
     swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
     swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
     swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
@@ -194,6 +208,8 @@ static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch
     swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
     swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval;
     swapchain_desc->auto_restore_display_mode = TRUE;
+
+    return TRUE;
 }
 
 /* Handle table functions */
@@ -505,7 +521,7 @@ static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface,
 
     wined3d_mutex_lock();
     hr = wined3d_device_set_cursor_properties(device->wined3d_device,
-            hotspot_x, hotspot_y, bitmap_impl->wined3d_surface);
+            hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -572,7 +588,8 @@ static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if
     }
     wined3d_mutex_unlock();
 
-    wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
+    if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters))
+        return D3DERR_INVALIDCALL;
     if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, &object)))
         *swapchain = &object->IDirect3DSwapChain8_iface;
     present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
@@ -637,6 +654,8 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
         WARN("App not active, returning D3DERR_DEVICELOST.\n");
         return D3DERR_DEVICELOST;
     }
+    if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters))
+        return D3DERR_INVALIDCALL;
 
     wined3d_mutex_lock();
 
@@ -653,7 +672,6 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
         device->index_buffer_size = 0;
     }
 
-    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
     if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
             NULL, reset_enum_callback, TRUE)))
     {
@@ -674,45 +692,51 @@ static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *s
         const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    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_device_present(device->wined3d_device, src_rect, dst_rect,
-            dst_window_override, dirty_region, 0);
-    wined3d_mutex_unlock();
-
-    return hr;
+    /* Fraps does not hook IDirect3DDevice8::Present regardless of the hotpatch
+     * attribute. It only hooks IDirect3DSwapChain8::Present. Yet it properly
+     * shows a framerate on Windows in applications that only call the device
+     * method, like e.g. the dx8 sdk samples. The conclusion is that native
+     * calls the swapchain's public method from the device. */
+    return IDirect3DSwapChain8_Present(&device->implicit_swapchain->IDirect3DSwapChain8_iface,
+            src_rect, dst_rect, dst_window_override, dirty_region);
 }
 
 static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    struct wined3d_surface *wined3d_surface = NULL;
+    struct wined3d_swapchain *wined3d_swapchain;
+    struct wined3d_resource *wined3d_resource;
+    struct wined3d_texture *wined3d_texture;
     struct d3d8_surface *surface_impl;
-    HRESULT hr;
 
     TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
             iface, backbuffer_idx, backbuffer_type, backbuffer);
 
+    /* backbuffer_type is ignored by native. */
+
+    /* No need to check for backbuffer == NULL, Windows crashes in that case. */
     wined3d_mutex_lock();
-    hr = wined3d_device_get_back_buffer(device->wined3d_device, 0, backbuffer_idx,
-            (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface);
-    if (SUCCEEDED(hr) && wined3d_surface && backbuffer)
+
+    wined3d_swapchain = device->implicit_swapchain->wined3d_swapchain;
+    if (!(wined3d_texture = wined3d_swapchain_get_back_buffer(wined3d_swapchain, backbuffer_idx)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
-        *backbuffer = &surface_impl->IDirect3DSurface8_iface;
-        IDirect3DSurface8_AddRef(*backbuffer);
+        wined3d_mutex_unlock();
+        *backbuffer = NULL;
+        return D3DERR_INVALIDCALL;
     }
-    wined3d_mutex_unlock();
 
-    return hr;
+    wined3d_resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
+    surface_impl = wined3d_resource_get_parent(wined3d_resource);
+    *backbuffer = &surface_impl->IDirect3DSurface8_iface;
+    IDirect3DSurface8_AddRef(*backbuffer);
+
+    wined3d_mutex_unlock();
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status)
@@ -1013,7 +1037,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
      * destination texture is in WINED3D_POOL_DEFAULT. */
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
+    wined3d_resource = wined3d_texture_get_sub_resource(src->wined3d_texture, src->sub_resource_idx);
     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
     if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
@@ -1025,7 +1049,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
     src_w = wined3d_desc.width;
     src_h = wined3d_desc.height;
 
-    wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
+    wined3d_resource = wined3d_texture_get_sub_resource(dst->wined3d_texture, dst->sub_resource_idx);
     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
     if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
@@ -1048,8 +1072,8 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
     if (!rect_count && !src_rects && !dst_points)
     {
         RECT rect = {0, 0, src_w, src_h};
-        wined3d_surface_blt(dst->wined3d_surface, &rect,
-                src->wined3d_surface, &rect, 0, NULL, WINED3D_TEXF_POINT);
+        wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &rect,
+                src->wined3d_texture, src->sub_resource_idx, &rect, 0, NULL, WINED3D_TEXF_POINT);
     }
     else
     {
@@ -1064,8 +1088,8 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
                 RECT dst_rect = {dst_points[i].x, dst_points[i].y,
                         dst_points[i].x + w, dst_points[i].y + h};
 
-                wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
-                        src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
+                wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect,
+                        src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
             }
         }
         else
@@ -1076,8 +1100,8 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
                 UINT h = src_rects[i].bottom - src_rects[i].top;
                 RECT dst_rect = {0, 0, w, h};
 
-                wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
-                        src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
+                wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect,
+                        src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
             }
         }
     }
@@ -1121,7 +1145,8 @@ static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirec
     }
 
     wined3d_mutex_lock();
-    hr = wined3d_device_get_front_buffer_data(device->wined3d_device, 0, dst_impl->wined3d_surface);
+    hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchain->wined3d_swapchain,
+            dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1157,13 +1182,13 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
                 return D3DERR_NOTFOUND;
             }
             original_surface = wined3d_rendertarget_view_get_sub_resource_parent(original_rtv);
-            wined3d_resource = wined3d_surface_get_resource(original_surface->wined3d_surface);
+            wined3d_resource = wined3d_texture_get_sub_resource(original_surface->wined3d_texture, original_surface->sub_resource_idx);
         }
         else
-            wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface);
+            wined3d_resource = wined3d_texture_get_sub_resource(rt_impl->wined3d_texture, rt_impl->sub_resource_idx);
         wined3d_resource_get_desc(wined3d_resource, &rt_desc);
 
-        wined3d_resource = wined3d_surface_get_resource(ds_impl->wined3d_surface);
+        wined3d_resource = wined3d_texture_get_sub_resource(ds_impl->wined3d_texture, ds_impl->sub_resource_idx);
         wined3d_resource_get_desc(wined3d_resource, &ds_desc);
 
         if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height)
@@ -1175,7 +1200,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
         if (ds_desc.multisample_type != rt_desc.multisample_type
                 || ds_desc.multisample_quality != rt_desc.multisample_quality)
         {
-            WARN("Multisample settings do not match, returing D3DERR_INVALIDCALL\n");
+            WARN("Multisample settings do not match, returning D3DERR_INVALIDCALL\n");
             wined3d_mutex_unlock();
             return D3DERR_INVALIDCALL;
 
@@ -2954,18 +2979,18 @@ static void CDECL device_parent_activate(struct wined3d_device_parent *device_pa
 }
 
 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_surface *surface, void **parent,
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, struct wined3d_surface *surface, void **parent,
         const struct wined3d_parent_ops **parent_ops)
 {
     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);
+    TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, surface, parent, parent_ops);
 
     if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
         return E_OUTOFMEMORY;
 
-    surface_init(d3d_surface, container_parent, surface, parent_ops);
+    surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
     *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
@@ -2973,50 +2998,42 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
 }
 
 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_volume *volume, void **parent,
-        const struct wined3d_parent_ops **parent_ops)
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+        void **parent, const struct wined3d_parent_ops **parent_ops)
 {
     struct d3d8_volume *d3d_volume;
 
-    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
-            device_parent, container_parent, volume, parent, parent_ops);
+    TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
 
     if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
         return E_OUTOFMEMORY;
 
-    volume_init(d3d_volume, container_parent, volume, parent_ops);
+    volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
     *parent = d3d_volume;
     TRACE("Created volume %p.\n", d3d_volume);
 
     return D3D_OK;
 }
 
-static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_texture **texture)
 {
     struct d3d8_device *device = device_from_device_parent(device_parent);
-    struct wined3d_resource_desc texture_desc;
     struct d3d8_surface *d3d_surface;
-    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
-            device_parent, container_parent, desc, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, texture %p.\n",
+            device_parent, container_parent, desc, texture);
 
-    texture_desc = *desc;
-    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
-    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, NULL, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1,
+            WINED3D_SURFACE_MAPPABLE, NULL, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
-    wined3d_surface_incref(*surface);
-    wined3d_texture_decref(texture);
-
-    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface = wined3d_resource_get_parent(wined3d_texture_get_sub_resource(*texture, 0));
     d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
 
     return hr;
@@ -3052,7 +3069,7 @@ static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
-    device_parent_create_swapchain_surface,
+    device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
 
@@ -3077,6 +3094,7 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
 {
     struct wined3d_swapchain_desc swapchain_desc;
+    struct wined3d_swapchain *wined3d_swapchain;
     HRESULT hr;
 
     device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl;
@@ -3129,7 +3147,14 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
     if (flags & D3DCREATE_MULTITHREADED)
         wined3d_device_set_multithreaded(device->wined3d_device);
 
-    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters);
+    if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters))
+    {
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+        return D3DERR_INVALIDCALL;
+    }
 
     hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc);
     if (FAILED(hr))
@@ -3156,6 +3181,9 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         goto err;
     }
 
+    wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
+    device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
+
     device->d3d_parent = &parent->IDirect3D8_iface;
     IDirect3D8_AddRef(device->d3d_parent);
 
index 3310036..2cfdc6d 100644 (file)
@@ -27,7 +27,7 @@ static inline struct d3d8_surface *impl_from_IDirect3DSurface8(IDirect3DSurface8
 
 static HRESULT WINAPI d3d8_surface_QueryInterface(IDirect3DSurface8 *iface, REFIID riid, void **out)
 {
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DSurface8)
             || IsEqualGUID(riid, &IID_IDirect3DResource8)
@@ -67,7 +67,7 @@ static ULONG WINAPI d3d8_surface_AddRef(IDirect3DSurface8 *iface)
         wined3d_mutex_lock();
         if (surface->wined3d_rtv)
             wined3d_rendertarget_view_incref(surface->wined3d_rtv);
-        wined3d_surface_incref(surface->wined3d_surface);
+        wined3d_texture_incref(surface->wined3d_texture);
         wined3d_mutex_unlock();
     }
 
@@ -97,7 +97,7 @@ static ULONG WINAPI d3d8_surface_Release(IDirect3DSurface8 *iface)
         wined3d_mutex_lock();
         if (surface->wined3d_rtv)
             wined3d_rendertarget_view_decref(surface->wined3d_rtv);
-        wined3d_surface_decref(surface->wined3d_surface);
+        wined3d_texture_decref(surface->wined3d_texture);
         wined3d_mutex_unlock();
 
         if (parent_device)
@@ -173,13 +173,13 @@ static HRESULT WINAPI d3d8_surface_GetDesc(IDirect3DSurface8 *iface, D3DSURFACE_
 {
     struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
     struct wined3d_resource_desc wined3d_desc;
-    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource *sub_resource;
 
     TRACE("iface %p, desc %p.\n", iface, desc);
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
-    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    sub_resource = wined3d_texture_get_sub_resource(surface->wined3d_texture, surface->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &wined3d_desc);
     wined3d_mutex_unlock();
 
     desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
@@ -198,6 +198,7 @@ static HRESULT WINAPI d3d8_surface_LockRect(IDirect3DSurface8 *iface,
         D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
 {
     struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_box box;
     struct wined3d_map_desc map_desc;
     HRESULT hr;
 
@@ -222,9 +223,16 @@ static HRESULT WINAPI d3d8_surface_LockRect(IDirect3DSurface8 *iface,
 
             return D3DERR_INVALIDCALL;
         }
+        box.left = rect->left;
+        box.top = rect->top;
+        box.right = rect->right;
+        box.bottom = rect->bottom;
+        box.front = 0;
+        box.back = 1;
     }
 
-    hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
+    hr = wined3d_resource_sub_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx,
+            &map_desc, rect ? &box : NULL, flags);
     wined3d_mutex_unlock();
 
     if (SUCCEEDED(hr))
@@ -249,7 +257,7 @@ static HRESULT WINAPI d3d8_surface_UnlockRect(IDirect3DSurface8 *iface)
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_unmap(surface->wined3d_surface);
+    hr = wined3d_resource_sub_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
     wined3d_mutex_unlock();
 
     switch(hr)
@@ -289,19 +297,20 @@ static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
-        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
+void surface_init(struct d3d8_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+        const struct wined3d_parent_ops **parent_ops)
 {
     IDirect3DBaseTexture8 *texture;
 
     surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl;
     d3d8_resource_init(&surface->resource);
     surface->resource.refcount = 0;
-    surface->wined3d_surface = wined3d_surface;
     list_init(&surface->rtv_entry);
-    surface->container = container_parent;
+    surface->container = wined3d_texture_get_parent(wined3d_texture);
+    surface->wined3d_texture = wined3d_texture;
+    surface->sub_resource_idx = sub_resource_idx;
 
-    if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
+    if (surface->container && SUCCEEDED(IUnknown_QueryInterface(surface->container,
             &IID_IDirect3DBaseTexture8, (void **)&texture)))
     {
         surface->texture = unsafe_impl_from_IDirect3DBaseTexture8(texture);
@@ -340,8 +349,8 @@ struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8
     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)))
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
+            surface->sub_resource_idx, surface, &d3d8_view_wined3d_parent_ops, &surface->wined3d_rtv)))
     {
         ERR("Failed to create rendertarget view, hr %#x.\n", hr);
         return NULL;
index c086635..f484fc8 100644 (file)
@@ -109,23 +109,33 @@ static HRESULT WINAPI d3d8_swapchain_GetBackBuffer(IDirect3DSwapChain8 *iface,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
 {
     struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
-    struct wined3d_surface *wined3d_surface = NULL;
+    struct wined3d_resource *wined3d_resource;
+    struct wined3d_texture *wined3d_texture;
     struct d3d8_surface *surface_impl;
     HRESULT hr = D3D_OK;
 
     TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
             iface, backbuffer_idx, backbuffer_type, backbuffer);
 
+    /* backbuffer_type is ignored by native. */
+
+    if (!backbuffer)
+    {
+        WARN("The output pointer is NULL, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain,
-            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type)))
+    if ((wined3d_texture = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain, backbuffer_idx)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        wined3d_resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
+        surface_impl = wined3d_resource_get_parent(wined3d_resource);
         *backbuffer = &surface_impl->IDirect3DSurface8_iface;
         IDirect3DSurface8_AddRef(*backbuffer);
     }
     else
     {
+        /* Do not set *backbuffer = NULL, see tests/device.c, test_swapchain(). */
         hr = D3DERR_INVALIDCALL;
     }
     wined3d_mutex_unlock();
index 03dc47e..1818f6d 100644 (file)
@@ -260,7 +260,7 @@ static UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3
     WORD stream = 0;
     int offset = 0;
 
-    TRACE("d3d8_elements %p, wined3d_elements %p\n", d3d8_elements, wined3d_elements);
+    TRACE("d3d8_elements %p, d3d8_elements_size %p, wined3d_elements %p\n", d3d8_elements, d3d8_elements_size, wined3d_elements);
 
     /* 128 should be enough for anyone... */
     *wined3d_elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * sizeof(**wined3d_elements));
index 8c94f53..302ee0d 100644 (file)
@@ -27,7 +27,7 @@ static inline struct d3d8_volume *impl_from_IDirect3DVolume8(IDirect3DVolume8 *i
 
 static HRESULT WINAPI d3d8_volume_QueryInterface(IDirect3DVolume8 *iface, REFIID riid, void **out)
 {
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DVolume8)
             || IsEqualGUID(riid, &IID_IUnknown))
@@ -113,13 +113,13 @@ static HRESULT WINAPI d3d8_volume_GetDesc(IDirect3DVolume8 *iface, D3DVOLUME_DES
 {
     struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
     struct wined3d_resource_desc wined3d_desc;
-    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource *sub_resource;
 
     TRACE("iface %p, desc %p.\n", iface, desc);
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_volume_get_resource(volume->wined3d_volume);
-    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    sub_resource = wined3d_texture_get_sub_resource(volume->wined3d_texture, volume->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &wined3d_desc);
     wined3d_mutex_unlock();
 
     desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
@@ -145,7 +145,8 @@ static HRESULT WINAPI d3d8_volume_LockBox(IDirect3DVolume8 *iface,
             iface, locked_box, box, flags);
 
     wined3d_mutex_lock();
-    hr = wined3d_volume_map(volume->wined3d_volume, &map_desc, (const struct wined3d_box *)box, flags);
+    hr = wined3d_resource_sub_resource_map(wined3d_texture_get_resource(volume->wined3d_texture), volume->sub_resource_idx,
+            &map_desc, (const struct wined3d_box *)box, flags);
     wined3d_mutex_unlock();
 
     locked_box->RowPitch = map_desc.row_pitch;
@@ -163,7 +164,7 @@ static HRESULT WINAPI d3d8_volume_UnlockBox(IDirect3DVolume8 *iface)
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_volume_unmap(volume->wined3d_volume);
+    hr = wined3d_resource_sub_resource_unmap(wined3d_texture_get_resource(volume->wined3d_texture), volume->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -198,14 +199,15 @@ static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-void volume_init(struct d3d8_volume *volume, struct d3d8_texture *texture,
-        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops)
+void volume_init(struct d3d8_volume *volume, struct wined3d_texture *wined3d_texture,
+        unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops)
 {
     volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl;
     d3d8_resource_init(&volume->resource);
     volume->resource.refcount = 0;
-    volume->wined3d_volume = wined3d_volume;
-    volume->texture = texture;
+    volume->texture = wined3d_texture_get_parent(wined3d_texture);
+    volume->wined3d_texture = wined3d_texture;
+    volume->sub_resource_idx = sub_resource_idx;
 
     *parent_ops = &d3d8_volume_wined3d_parent_ops;
 }
index 300a5f0..86177b7 100644 (file)
@@ -173,6 +173,9 @@ struct d3d9_device
     LONG device_state;
     BOOL in_destruction;
     BOOL in_scene;
+
+    UINT implicit_swapchain_count;
+    struct d3d9_swapchain **implicit_swapchains;
 };
 
 HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d,
@@ -197,12 +200,13 @@ struct d3d9_volume
 {
     IDirect3DVolume9 IDirect3DVolume9_iface;
     struct d3d9_resource resource;
-    struct wined3d_volume *wined3d_volume;
+    struct wined3d_texture *wined3d_texture;
+    unsigned int sub_resource_idx;
     struct d3d9_texture *texture;
 };
 
-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;
+void volume_init(struct d3d9_volume *volume, struct wined3d_texture *wined3d_texture,
+        unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d9_swapchain
 {
@@ -219,6 +223,8 @@ struct d3d9_surface
 {
     IDirect3DSurface9 IDirect3DSurface9_iface;
     struct d3d9_resource resource;
+    struct wined3d_texture *wined3d_texture;
+    unsigned int sub_resource_idx;
     struct wined3d_surface *wined3d_surface;
     struct list rtv_entry;
     struct wined3d_rendertarget_view *wined3d_rtv;
@@ -229,7 +235,7 @@ struct d3d9_surface
 };
 
 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,
+void surface_init(struct d3d9_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
         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;
 
index 2d55f3c..3fef885 100644 (file)
@@ -205,9 +205,25 @@ void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *prese
     present_parameters->PresentationInterval = swapchain_desc->swap_interval;
 }
 
-static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
-        const D3DPRESENT_PARAMETERS *present_parameters)
+static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
+        const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended)
 {
+    D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY;
+    UINT highest_bb_count = extended ? 30 : 3;
+
+    if (!present_parameters->SwapEffect || present_parameters->SwapEffect > highest_swapeffect)
+    {
+        WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
+        return FALSE;
+    }
+    if (present_parameters->BackBufferCount > highest_bb_count
+            || (present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
+            && present_parameters->BackBufferCount > 1))
+    {
+        WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
+        return FALSE;
+    }
+
     swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
     swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
     swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
@@ -224,6 +240,8 @@ static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch
     swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
     swapchain_desc->swap_interval = present_parameters->PresentationInterval;
     swapchain_desc->auto_restore_display_mode = TRUE;
+
+    return TRUE;
 }
 
 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
@@ -301,6 +319,8 @@ static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *if
         if (device->index_buffer)
             wined3d_buffer_decref(device->index_buffer);
 
+        HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
+
         wined3d_device_uninit_3d(device->wined3d_device);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
@@ -463,7 +483,7 @@ static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface,
 
     wined3d_mutex_lock();
     hr = wined3d_device_set_cursor_properties(device->wined3d_device,
-            hotspot_x, hotspot_y, bitmap_impl->wined3d_surface);
+            hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -530,7 +550,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(ID
     }
     wined3d_mutex_unlock();
 
-    wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
+    if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters,
+            device->d3d_parent->extended))
+        return D3DERR_INVALIDCALL;
     if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object)))
         *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
     present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
@@ -542,19 +564,16 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice
         UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    struct wined3d_swapchain *wined3d_swapchain;
-    struct d3d9_swapchain *swapchain_impl;
     HRESULT hr;
 
     TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
 
     wined3d_mutex_lock();
-    if ((wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, swapchain_idx)))
+    if (swapchain_idx < device->implicit_swapchain_count)
     {
-       swapchain_impl = wined3d_swapchain_get_parent(wined3d_swapchain);
-       *swapchain = (IDirect3DSwapChain9 *)&swapchain_impl->IDirect3DSwapChain9Ex_iface;
-       IDirect3DSwapChain9Ex_AddRef(*swapchain);
-       hr = D3D_OK;
+        *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface;
+        IDirect3DSwapChain9Ex_AddRef(*swapchain);
+        hr = D3D_OK;
     }
     else
     {
@@ -623,6 +642,25 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
     return D3D_OK;
 }
 
+static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device)
+{
+    UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
+    struct wined3d_swapchain *wined3d_swapchain;
+
+    if (!(device->implicit_swapchains = HeapAlloc(GetProcessHeap(), 0,
+            new_swapchain_count * sizeof(*device->implicit_swapchains))))
+        return E_OUTOFMEMORY;
+
+    for (i = 0; i < new_swapchain_count; ++i)
+    {
+        wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
+        device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
+    }
+    device->implicit_swapchain_count = new_swapchain_count;
+
+    return D3D_OK;
+}
+
 static HRESULT d3d9_device_reset(struct d3d9_device *device,
         D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
 {
@@ -645,6 +683,10 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
         wined3d_mode.scanline_ordering = mode->ScanLineOrdering;
     }
 
+    if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters,
+            device->d3d_parent->extended))
+        return D3DERR_INVALIDCALL;
+
     wined3d_mutex_lock();
 
     if (device->vertex_buffer)
@@ -661,20 +703,25 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
         device->index_buffer_size = 0;
     }
 
-    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
     if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
             mode ? &wined3d_mode : NULL, reset_enum_callback, !device->d3d_parent->extended)))
     {
-        struct wined3d_swapchain *wined3d_swapchain;
+        HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
 
-        wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
-        wined3d_swapchain_get_desc(wined3d_swapchain, &swapchain_desc);
-        present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
-        present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
-        present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
-        present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
+        if (FAILED(hr = d3d9_device_get_swapchains(device)))
+        {
+            device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
+        }
+        else
+        {
+            wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
+            present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
+            present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
+            present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
+            present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
 
-        device->device_state = D3D9_DEVICE_STATE_OK;
+            device->device_state = D3D9_DEVICE_STATE_OK;
+        }
     }
     else if (!device->d3d_parent->extended)
     {
@@ -700,6 +747,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    UINT i;
     HRESULT hr;
 
     TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
@@ -709,37 +757,50 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *
         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);
+    for (i = 0; i < device->implicit_swapchain_count; ++i)
+    {
+        hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
+                dst_rect, dst_window_override, dirty_region, 0);
+        if (FAILED(hr))
+        {
+            wined3d_mutex_unlock();
+            return hr;
+        }
+    }
     wined3d_mutex_unlock();
 
-    return hr;
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    struct wined3d_surface *wined3d_surface = NULL;
-    struct d3d9_surface *surface_impl;
     HRESULT hr;
 
     TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
             iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer);
 
+    /* backbuffer_type is ignored by native. */
+
+    /* No need to check for backbuffer == NULL, Windows crashes in that case. */
+    *backbuffer = NULL;
+
     wined3d_mutex_lock();
-    hr = wined3d_device_get_back_buffer(device->wined3d_device, swapchain,
-            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface);
-    if (SUCCEEDED(hr) && wined3d_surface && backbuffer)
+    if (swapchain >= device->implicit_swapchain_count)
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
-        *backbuffer = &surface_impl->IDirect3DSurface9_iface;
-        IDirect3DSurface9_AddRef(*backbuffer);
+        wined3d_mutex_unlock();
+        WARN("Swapchain index %u is out of range, returning D3DERR_INVALIDCALL.\n", swapchain);
+        return D3DERR_INVALIDCALL;
     }
+
+    hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface,
+            backbuffer_idx, backbuffer_type, backbuffer);
     wined3d_mutex_unlock();
 
     return hr;
 }
+
 static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface,
         UINT swapchain, D3DRASTER_STATUS *raster_status)
 {
@@ -1201,12 +1262,22 @@ static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface,
 {
     struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target);
     struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *sub_resource;
     HRESULT hr;
 
     TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface);
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_get_render_target_data(dst_impl->wined3d_surface, rt_impl->wined3d_surface);
+    sub_resource = wined3d_texture_get_sub_resource(rt_impl->wined3d_texture, rt_impl->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+
+    /* TODO: Check surface sizes, pools, etc. */
+    if (wined3d_desc.multisample_type)
+        hr = D3DERR_INVALIDCALL;
+    else
+        hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, NULL,
+                rt_impl->wined3d_texture, rt_impl->sub_resource_idx, NULL, 0, NULL, WINED3D_TEXF_POINT);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1217,12 +1288,14 @@ static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
-    HRESULT hr;
+    HRESULT hr = D3DERR_INVALIDCALL;
 
     TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface);
 
     wined3d_mutex_lock();
-    hr = wined3d_device_get_front_buffer_data(device->wined3d_device, swapchain, dst_impl->wined3d_surface);
+    if (swapchain < device->implicit_swapchain_count)
+        hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain,
+                dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1236,17 +1309,17 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect
     struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
     HRESULT hr = D3DERR_INVALIDCALL;
     struct wined3d_resource_desc src_desc, dst_desc;
-    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource *sub_resource;
 
     TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
             iface, src_surface, src_rect, dst_surface, dst_rect, filter);
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
-    wined3d_resource_get_desc(wined3d_resource, &dst_desc);
+    sub_resource = wined3d_texture_get_sub_resource(dst->wined3d_texture, dst->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &dst_desc);
 
-    wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
-    wined3d_resource_get_desc(wined3d_resource, &src_desc);
+    sub_resource = wined3d_texture_get_sub_resource(src->wined3d_texture, src->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &src_desc);
 
     if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
@@ -1283,7 +1356,8 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect
         }
     }
 
-    hr = wined3d_surface_blt(dst->wined3d_surface, dst_rect, src->wined3d_surface, src_rect, 0, NULL, filter);
+    hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect,
+            src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter);
     if (hr == WINEDDERR_INVALIDRECT)
         hr = D3DERR_INVALIDCALL;
 
@@ -1312,7 +1386,11 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
 
     wined3d_mutex_lock();
 
-    wined3d_resource = wined3d_surface_get_resource(surface_impl->wined3d_surface);
+    if (!(wined3d_resource = wined3d_texture_get_sub_resource(surface_impl->wined3d_texture, surface_impl->sub_resource_idx)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
     wined3d_resource_get_desc(wined3d_resource, &desc);
 
     if (desc.pool != WINED3D_POOL_DEFAULT)
@@ -3148,6 +3226,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex
         const RGNDATA *dirty_region, DWORD flags)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    UINT i;
     HRESULT hr;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
@@ -3158,11 +3237,18 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex
         return S_PRESENT_OCCLUDED;
 
     wined3d_mutex_lock();
-    hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
-            dst_window_override, dirty_region, flags);
+    for (i = 0; i < device->implicit_swapchain_count; ++i)
+    {
+        if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
+                dst_rect, dst_window_override, dirty_region, flags)))
+        {
+            wined3d_mutex_unlock();
+            return hr;
+        }
+    }
     wined3d_mutex_unlock();
 
-    return hr;
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
@@ -3215,13 +3301,11 @@ static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HW
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct wined3d_swapchain_desc swapchain_desc;
-    struct wined3d_swapchain *swapchain;
 
     TRACE("iface %p, dst_window %p.\n", iface, dst_window);
 
     wined3d_mutex_lock();
-    swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
-    wined3d_swapchain_get_desc(swapchain, &swapchain_desc);
+    wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
     wined3d_mutex_unlock();
 
     if (swapchain_desc.windowed)
@@ -3492,18 +3576,18 @@ static void CDECL device_parent_activate(struct wined3d_device_parent *device_pa
 }
 
 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_surface *surface, void **parent,
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, struct wined3d_surface *surface, void **parent,
         const struct wined3d_parent_ops **parent_ops)
 {
     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);
+    TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, surface, parent, parent_ops);
 
     if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
         return E_OUTOFMEMORY;
 
-    surface_init(d3d_surface, container_parent, surface, parent_ops);
+    surface_init(d3d_surface, wined3d_texture, sub_resource_idx, surface, parent_ops);
     *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
@@ -3511,53 +3595,45 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
 }
 
 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_volume *volume, void **parent,
-        const struct wined3d_parent_ops **parent_ops)
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+        void **parent, const struct wined3d_parent_ops **parent_ops)
 {
     struct d3d9_volume *d3d_volume;
 
-    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
-            device_parent, container_parent, volume, parent, parent_ops);
+    TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
 
     if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
         return E_OUTOFMEMORY;
 
-    volume_init(d3d_volume, container_parent, volume, parent_ops);
+    volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
     *parent = d3d_volume;
     TRACE("Created volume %p.\n", d3d_volume);
 
     return D3D_OK;
 }
 
-static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_texture **texture)
 {
     struct d3d9_device *device = device_from_device_parent(device_parent);
-    struct wined3d_resource_desc texture_desc;
     struct d3d9_surface *d3d_surface;
-    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
-            device_parent, container_parent, desc, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, texture %p.\n",
+            device_parent, container_parent, desc, texture);
 
     if (container_parent == device_parent)
         container_parent = &device->IDirect3DDevice9Ex_iface;
 
-    texture_desc = *desc;
-    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
-    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, NULL, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1,
+            WINED3D_SURFACE_MAPPABLE, NULL, container_parent, &d3d9_null_wined3d_parent_ops, texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
-    wined3d_surface_incref(*surface);
-    wined3d_texture_decref(texture);
-
-    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface = wined3d_resource_get_parent(wined3d_texture_get_sub_resource(*texture, 0));
     d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface;
 
     return hr;
@@ -3594,7 +3670,7 @@ static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
-    device_parent_create_swapchain_surface,
+    device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
 
@@ -3680,6 +3756,7 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
     if (!swapchain_desc)
     {
         ERR("Failed to allocate wined3d parameters.\n");
+        wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
         return E_OUTOFMEMORY;
@@ -3687,7 +3764,15 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
 
     for (i = 0; i < count; ++i)
     {
-        wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], &parameters[i]);
+        if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], &parameters[i],
+                parent->extended))
+        {
+            wined3d_device_release_focus_window(device->wined3d_device);
+            wined3d_device_decref(device->wined3d_device);
+            HeapFree(GetProcessHeap(), 0, swapchain_desc);
+            wined3d_mutex_unlock();
+            return D3DERR_INVALIDCALL;
+        }
     }
 
     hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc);
@@ -3701,12 +3786,22 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
         return hr;
     }
 
-    wined3d_mutex_unlock();
+    if (FAILED(hr = d3d9_device_get_swapchains(device)))
+    {
+        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        return E_OUTOFMEMORY;
+    }
 
     for (i = 0; i < count; ++i)
     {
         present_parameters_from_wined3d_swapchain_desc(&parameters[i], &swapchain_desc[i]);
     }
+
+    wined3d_mutex_unlock();
+
     HeapFree(GetProcessHeap(), 0, swapchain_desc);
 
     /* Initialize the converted declaration array. This creates a valid pointer
@@ -3716,6 +3811,7 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
     {
         ERR("Failed to allocate FVF vertex declaration map memory.\n");
         wined3d_mutex_lock();
+        HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
         wined3d_device_uninit_3d(device->wined3d_device);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
index 578476d..606e84d 100644 (file)
@@ -29,7 +29,7 @@ static inline struct d3d9_query *impl_from_IDirect3DQuery9(IDirect3DQuery9 *ifac
 
 static HRESULT WINAPI d3d9_query_QueryInterface(IDirect3DQuery9 *iface, REFIID riid, void **out)
 {
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DQuery9)
             || IsEqualGUID(riid, &IID_IUnknown))
index df11181..f1ad1f1 100644 (file)
@@ -179,7 +179,7 @@ static void WINAPI d3d9_surface_PreLoad(IDirect3DSurface9 *iface)
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    wined3d_surface_preload(surface->wined3d_surface);
+    wined3d_texture_preload(surface->wined3d_texture);
     wined3d_mutex_unlock();
 }
 
@@ -211,13 +211,13 @@ static HRESULT WINAPI d3d9_surface_GetDesc(IDirect3DSurface9 *iface, D3DSURFACE_
 {
     struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
     struct wined3d_resource_desc wined3d_desc;
-    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource *sub_resource;
 
     TRACE("iface %p, desc %p.\n", iface, desc);
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
-    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    sub_resource = wined3d_texture_get_sub_resource(surface->wined3d_texture, surface->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &wined3d_desc);
     wined3d_mutex_unlock();
 
     desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
@@ -236,14 +236,26 @@ static HRESULT WINAPI d3d9_surface_LockRect(IDirect3DSurface9 *iface,
         D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
 {
     struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_box box;
     struct wined3d_map_desc map_desc;
     HRESULT hr;
 
     TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n",
             iface, locked_rect, wine_dbgstr_rect(rect), flags);
 
+    if (rect)
+    {
+        box.left = rect->left;
+        box.top = rect->top;
+        box.right = rect->right;
+        box.bottom = rect->bottom;
+        box.front = 0;
+        box.back = 1;
+    }
+
     wined3d_mutex_lock();
-    hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
+    hr = wined3d_resource_sub_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx,
+            &map_desc, rect ? &box : NULL, flags);
     wined3d_mutex_unlock();
 
     if (SUCCEEDED(hr))
@@ -263,7 +275,7 @@ static HRESULT WINAPI d3d9_surface_UnlockRect(IDirect3DSurface9 *iface)
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_unmap(surface->wined3d_surface);
+    hr = wined3d_resource_sub_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
     wined3d_mutex_unlock();
 
     switch(hr)
@@ -288,7 +300,7 @@ static HRESULT WINAPI d3d9_surface_GetDC(IDirect3DSurface9 *iface, HDC *dc)
     }
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_getdc(surface->wined3d_surface, dc);
+    hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
     wined3d_mutex_unlock();
 
     return hr;
@@ -302,7 +314,7 @@ static HRESULT WINAPI d3d9_surface_ReleaseDC(IDirect3DSurface9 *iface, HDC dc)
     TRACE("iface %p, dc %p.\n", iface, dc);
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_releasedc(surface->wined3d_surface, dc);
+    hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
     wined3d_mutex_unlock();
 
     switch (hr)
@@ -348,7 +360,7 @@ static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
+void surface_init(struct d3d9_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
         struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
 {
     struct wined3d_resource_desc desc;
@@ -359,16 +371,18 @@ void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
     surface->resource.refcount = 0;
     surface->wined3d_surface = wined3d_surface;
     list_init(&surface->rtv_entry);
-    surface->container = container_parent;
+    surface->container = wined3d_texture_get_parent(wined3d_texture);
+    surface->wined3d_texture = wined3d_texture;
+    surface->sub_resource_idx = sub_resource_idx;
 
-    if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
+    if (surface->container && SUCCEEDED(IUnknown_QueryInterface(surface->container,
             &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);
+    wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &desc);
     switch (d3dformat_from_wined3dformat(desc.format))
     {
         case D3DFMT_A8R8G8B8:
@@ -417,8 +431,8 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9
     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)))
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
+            surface->sub_resource_idx, surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
     {
         ERR("Failed to create rendertarget view, hr %#x.\n", hr);
         return NULL;
index 6698a8b..d0e931e 100644 (file)
@@ -139,7 +139,7 @@ static HRESULT WINAPI d3d9_swapchain_GetFrontBufferData(IDirect3DSwapChain9Ex *i
     TRACE("iface %p, surface %p.\n", iface, surface);
 
     wined3d_mutex_lock();
-    hr = wined3d_swapchain_get_front_buffer_data(swapchain->wined3d_swapchain, dst->wined3d_surface);
+    hr = wined3d_swapchain_get_front_buffer_data(swapchain->wined3d_swapchain, dst->wined3d_texture, dst->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -149,23 +149,33 @@ static HRESULT WINAPI d3d9_swapchain_GetBackBuffer(IDirect3DSwapChain9Ex *iface,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
 {
     struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
-    struct wined3d_surface *wined3d_surface = NULL;
+    struct wined3d_resource *wined3d_resource;
+    struct wined3d_texture *wined3d_texture;
     struct d3d9_surface *surface_impl;
     HRESULT hr = D3D_OK;
 
     TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
             iface, backbuffer_idx, backbuffer_type, backbuffer);
 
+    /* backbuffer_type is ignored by native. */
+
+    if (!backbuffer)
+    {
+        WARN("The output pointer is NULL, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain,
-            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type)))
+    if ((wined3d_texture = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain, backbuffer_idx)))
     {
-       surface_impl = wined3d_surface_get_parent(wined3d_surface);
-       *backbuffer = &surface_impl->IDirect3DSurface9_iface;
-       IDirect3DSurface9_AddRef(*backbuffer);
+        wined3d_resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
+        surface_impl = wined3d_resource_get_parent(wined3d_resource);
+        *backbuffer = &surface_impl->IDirect3DSurface9_iface;
+        IDirect3DSurface9_AddRef(*backbuffer);
     }
     else
     {
+        /* Do not set *backbuffer = NULL, see tests/device.c, test_swapchain(). */
         hr = D3DERR_INVALIDCALL;
     }
     wined3d_mutex_unlock();
index 4072748..03c7394 100644 (file)
@@ -1249,9 +1249,15 @@ struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture
 {
     if (!iface)
         return NULL;
-    assert(iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl
-            || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl
-            || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl);
+
+    if (iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl)
+    {
+        WARN("%p is not a valid IDirect3DBaseTexture9 interface.\n", iface);
+        return NULL;
+    }
+
     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
 }
 
index 88f4d43..5b3ae91 100644 (file)
@@ -323,7 +323,7 @@ static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9 *d3d9_elem
     UINT count = 1;
     UINT i;
 
-    TRACE("d3d9_elements %p, wined3d_elements %p\n", d3d9_elements, wined3d_elements);
+    TRACE("d3d9_elements %p, wined3d_elements %p, element_count %p\n", d3d9_elements, wined3d_elements, element_count);
 
     element = d3d9_elements;
     while (element++->Stream != 0xff && count++ < 128);
index 9a7aad6..245612e 100644 (file)
@@ -114,13 +114,13 @@ static HRESULT WINAPI d3d9_volume_GetDesc(IDirect3DVolume9 *iface, D3DVOLUME_DES
 {
     struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
     struct wined3d_resource_desc wined3d_desc;
-    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource *sub_resource;
 
     TRACE("iface %p, desc %p.\n", iface, desc);
 
     wined3d_mutex_lock();
-    wined3d_resource = wined3d_volume_get_resource(volume->wined3d_volume);
-    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    sub_resource = wined3d_texture_get_sub_resource(volume->wined3d_texture, volume->sub_resource_idx);
+    wined3d_resource_get_desc(sub_resource, &wined3d_desc);
     wined3d_mutex_unlock();
 
     desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
@@ -145,7 +145,8 @@ static HRESULT WINAPI d3d9_volume_LockBox(IDirect3DVolume9 *iface,
             iface, locked_box, box, flags);
 
     wined3d_mutex_lock();
-    hr = wined3d_volume_map(volume->wined3d_volume, &map_desc, (const struct wined3d_box *)box, flags);
+    hr = wined3d_resource_sub_resource_map(wined3d_texture_get_resource(volume->wined3d_texture), volume->sub_resource_idx,
+            &map_desc, (const struct wined3d_box *)box, flags);
     wined3d_mutex_unlock();
 
     locked_box->RowPitch = map_desc.row_pitch;
@@ -163,7 +164,7 @@ static HRESULT WINAPI d3d9_volume_UnlockBox(IDirect3DVolume9 *iface)
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_volume_unmap(volume->wined3d_volume);
+    hr = wined3d_resource_sub_resource_unmap(wined3d_texture_get_resource(volume->wined3d_texture), volume->sub_resource_idx);
     wined3d_mutex_unlock();
 
     return hr;
@@ -198,14 +199,15 @@ static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-void volume_init(struct d3d9_volume *volume, struct d3d9_texture *texture,
-        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops)
+void volume_init(struct d3d9_volume *volume, struct wined3d_texture *wined3d_texture,
+        unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops)
 {
     volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
     d3d9_resource_init(&volume->resource);
     volume->resource.refcount = 0;
-    volume->wined3d_volume = wined3d_volume;
-    volume->texture = texture;
+    volume->texture = wined3d_texture_get_parent(wined3d_texture);
+    volume->wined3d_texture = wined3d_texture;
+    volume->sub_resource_idx = sub_resource_idx;
 
     *parent_ops = &d3d9_volume_wined3d_parent_ops;
 }
index 3c5b7b0..5c3ec3d 100644 (file)
@@ -1415,6 +1415,28 @@ HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
     return DD_OK;
 }
 
+HRESULT CALLBACK enum_zbuffer(DDPIXELFORMAT *format, void *ctx)
+{
+    DDCAPS *caps = ctx;
+
+    switch (format->u1.dwZBufferBitDepth)
+    {
+        case 8:
+            caps->dwZBufferBitDepths |= DDBD_8;
+            break;
+        case 16:
+            caps->dwZBufferBitDepths |= DDBD_16;
+            break;
+        case 24:
+            caps->dwZBufferBitDepths |= DDBD_24;
+            break;
+        case 32:
+            caps->dwZBufferBitDepths |= DDBD_32;
+            break;
+    }
+    return D3DENUMRET_OK;
+}
+
 /*****************************************************************************
  * IDirectDraw7::GetCaps
  *
@@ -1495,6 +1517,8 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
     caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
     caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
 
+    IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
+
     if(DriverCaps)
     {
         DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
@@ -3129,6 +3153,7 @@ static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
     {
          IDirectDrawSurface7 *surface;
          DDSURFACEDESC2 testdesc;
+         HRESULT hr;
 
         if (match_flags != DDENUMSURFACES_MATCH)
             return DDERR_INVALIDPARAMS;
@@ -3137,33 +3162,32 @@ static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
             return DDERR_INVALIDPARAMS;
 
         memcpy(&testdesc, DDSD, sizeof(testdesc));
-
         if (!(testdesc.dwFlags & DDSD_WIDTH))
         {
             testdesc.dwFlags |= DDSD_WIDTH;
             testdesc.dwWidth = 512;
         }
-
         if (!(testdesc.dwFlags & DDSD_HEIGHT))
         {
             testdesc.dwFlags |= DDSD_HEIGHT;
             testdesc.dwHeight = 512;
         }
 
-        if (IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL) == DD_OK)
+        hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
+        if (SUCCEEDED(hr))
         {
             surf = unsafe_impl_from_IDirectDrawSurface7(surface);
             Callback(NULL, &surf->surface_desc, Context);
             IDirectDrawSurface7_Release(surface);
         }
         else
-            FIXME("Failed to create surface!\n");
+            ERR("Failed to create surface, hr %#x.\n", hr);
     }
     else if (Flags & DDENUMSURFACES_DOESEXIST)
     {
+        BOOL all, nomatch;
         DDSURFACEDESC2 desc;
         struct list *entry, *entry2;
-        BOOL nomatch, all;
 
         /* a combination of match flags is not allowed */
         if (match_flags != 0 &&
@@ -4111,7 +4135,7 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    if (SUCCEEDED(hr = d3d_device_create(ddraw, target, (IUnknown *)surface, 7, &object, NULL)))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL)))
     {
         *device = &object->IDirect3DDevice7_iface;
     }
@@ -4140,7 +4164,7 @@ static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
         return CLASS_E_NOAGGREGATION;
 
     wined3d_mutex_lock();
-    if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
     {
         *device = &device_impl->IDirect3DDevice3_iface;
     }
@@ -4166,7 +4190,7 @@ static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
             iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
     {
         *device = &device_impl->IDirect3DDevice2_iface;
     }
@@ -4540,7 +4564,7 @@ static const struct IDirectDraw2Vtbl ddraw2_vtbl =
     ddraw2_GetAvailableVidMem,
 };
 
-static const struct IDirectDrawVtbl ddraw1_vtbl =
+static struct IDirectDrawVtbl ddraw1_vtbl =
 {
     /* IUnknown */
     ddraw1_QueryInterface,
@@ -4758,17 +4782,17 @@ static void CDECL device_parent_activate(struct wined3d_device_parent *device_pa
 }
 
 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_surface *surface,
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, struct wined3d_surface *surface,
         void **parent, const struct wined3d_parent_ops **parent_ops)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
     struct ddraw_surface *ddraw_surface;
 
-    TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
-            device_parent, container_parent, surface, parent, parent_ops);
+    TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, surface, parent, parent_ops);
 
     /* We have a swapchain or wined3d internal texture. */
-    if (!container_parent || container_parent == ddraw)
+    if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw)
     {
         *parent = NULL;
         *parent_ops = &ddraw_null_wined3d_parent_ops;
@@ -4782,7 +4806,7 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
         return DDERR_OUTOFVIDEOMEMORY;
     }
 
-    ddraw_surface_init(ddraw_surface, ddraw, container_parent, surface, parent_ops);
+    ddraw_surface_init(ddraw_surface, ddraw, wined3d_texture_get_parent(wined3d_texture), surface, parent_ops);
     *parent = ddraw_surface;
     list_add_head(&ddraw->surface_list, &ddraw_surface->surface_list_entry);
 
@@ -4792,11 +4816,11 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
 }
 
 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
-        void *container_parent, struct wined3d_volume *volume,
+        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
         void **parent, const struct wined3d_parent_ops **parent_ops)
 {
-    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
-            device_parent, container_parent, volume, parent, parent_ops);
+    TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
+            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
 
     *parent = NULL;
     *parent_ops = &ddraw_null_wined3d_parent_ops;
@@ -4815,16 +4839,14 @@ static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops =
     ddraw_frontbuffer_destroyed,
 };
 
-static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_texture **texture)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
-    struct wined3d_resource_desc texture_desc;
-    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
-            device_parent, container_parent, desc, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, texture %p.\n",
+            device_parent, container_parent, desc, texture);
 
     if (ddraw->wined3d_frontbuffer)
     {
@@ -4832,19 +4854,14 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
         return E_FAIL;
     }
 
-    texture_desc = *desc;
-    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
-    if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, &texture)))
+    if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1,
+            WINED3D_SURFACE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
-    ddraw->wined3d_frontbuffer = *surface;
-    wined3d_surface_incref(*surface);
-    wined3d_texture_decref(texture);
+    ddraw->wined3d_frontbuffer = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(*texture, 0));
 
     return hr;
 }
@@ -4877,7 +4894,7 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
-    device_parent_create_swapchain_surface,
+    device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
 
index 42cfd7c..9ecfcec 100644 (file)
@@ -191,9 +191,6 @@ struct ddraw_surface
     /* Surface description, for GetAttachedSurface */
     DDSURFACEDESC2          surface_desc;
 
-    /* Misc things */
-    UINT                    mipmap_level;
-
     /* Clipper objects */
     struct ddraw_clipper *clipper;
     struct ddraw_palette *palette;
@@ -304,6 +301,7 @@ struct d3d_device
     IUnknown IUnknown_inner;
     LONG ref;
     UINT version;
+    BOOL hw;
 
     IUnknown *outer_unknown;
     struct wined3d_device *wined3d_device;
@@ -346,7 +344,7 @@ struct d3d_device
     D3DMATRIXHANDLE          world, proj, view;
 };
 
-HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
+HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface *target, IUnknown *rt_iface,
         UINT version, struct d3d_device **device, IUnknown *outer_unknown) DECLSPEC_HIDDEN;
 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device) DECLSPEC_HIDDEN;
 
index 963416d..33b01e5 100644 (file)
@@ -1853,7 +1853,7 @@ static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
         return DDERR_INVALIDCAPS;
     }
 
-    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
     {
         WARN("Surface %p is not in video memory.\n", target_impl);
         wined3d_mutex_unlock();
@@ -1929,7 +1929,7 @@ static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
         return DDERR_INVALIDPIXELFORMAT;
     }
 
-    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
     {
         WARN("Surface %p is not in video memory.\n", target_impl);
         IDirectDrawSurface4_AddRef(target);
@@ -1978,7 +1978,7 @@ static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
         return DDERR_INVALIDPIXELFORMAT;
     }
 
-    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
     {
         WARN("Surface %p is not in video memory.\n", target_impl);
         IDirectDrawSurface_AddRef(target);
@@ -6773,7 +6773,7 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device
     return WINED3D_ZB_TRUE;
 }
 
-static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
+static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, BOOL hw,
         struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
 {
     static const D3DMATRIX ident =
@@ -6796,6 +6796,7 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
     device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
     device->ref = 1;
     device->version = version;
+    device->hw = hw;
 
     if (outer_unknown)
         device->outer_unknown = outer_unknown;
@@ -6846,14 +6847,18 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
     return D3D_OK;
 }
 
-HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
+HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface *target, IUnknown *rt_iface,
         UINT version, struct d3d_device **device, IUnknown *outer_unknown)
 {
     struct d3d_device *object;
+    BOOL hw = TRUE;
     HRESULT hr;
 
-    TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
-            ddraw, target, version, device, outer_unknown);
+    TRACE("ddraw %p, guid %s, target %p, version %u, device %p, outer_unknown %p.\n",
+            ddraw, debugstr_guid(guid), target, version, device, outer_unknown);
+
+    if (IsEqualGUID(guid, &IID_IDirect3DRGBDevice))
+        hw = FALSE;
 
     if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
             || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
@@ -6868,7 +6873,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUn
         return DDERR_NOPALETTEATTACHED;
     }
 
-    if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    if (hw && !(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
     {
         WARN("Surface %p is not in video memory.\n", target);
         return D3DERR_SURFACENOTINVIDMEM;
@@ -6895,7 +6900,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUn
         return DDERR_OUTOFMEMORY;
     }
 
-    if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
+    if (FAILED(hr = d3d_device_init(object, ddraw, hw, target, rt_iface, version, outer_unknown)))
     {
         WARN("Failed to initialize device, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
index 230af86..4a49287 100644 (file)
@@ -42,7 +42,7 @@ struct callback_info
 };
 
 /* Enumeration callback for converting DirectDrawEnumerateA to DirectDrawEnumerateExA */
-static HRESULT CALLBACK enum_callback(GUID *guid, char *description, char *driver_name,
+static BOOL CALLBACK enum_callback(GUID *guid, char *description, char *driver_name,
                                       void *context, HMONITOR monitor)
 {
     const struct callback_info *info = context;
index f8849c0..5fe675a 100644 (file)
@@ -206,7 +206,7 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface,
             {
                 HRESULT hr;
 
-                if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown *)&This->IDirectDrawSurface_iface,
+                if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
                         1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
                 {
                     This->device1 = NULL;
@@ -772,7 +772,6 @@ static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *ifa
              */
 
             TRACE("(%p): Returning surface %p\n", This, surf);
-            TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
             *Surface = &surf->IDirectDrawSurface7_iface;
             ddraw_surface7_AddRef(*Surface);
             wined3d_mutex_unlock();
@@ -949,6 +948,7 @@ static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *ifac
 static HRESULT surface_lock(struct ddraw_surface *This,
         RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
 {
+    struct wined3d_box box;
     struct wined3d_map_desc map_desc;
     HRESULT hr = DD_OK;
 
@@ -980,12 +980,18 @@ static HRESULT surface_lock(struct ddraw_surface *This,
             wined3d_mutex_unlock();
             return DDERR_INVALIDPARAMS;
         }
+        box.left = Rect->left;
+        box.top = Rect->top;
+        box.right = Rect->right;
+        box.bottom = Rect->bottom;
+        box.front = 0;
+        box.back = 1;
     }
 
     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         hr = ddraw_surface_update_frontbuffer(This, Rect, TRUE);
     if (SUCCEEDED(hr))
-        hr = wined3d_surface_map(This->wined3d_surface, &map_desc, Rect, Flags);
+        hr = wined3d_surface_map(This->wined3d_surface, &map_desc, Rect ? &box : NULL, Flags);
     if (FAILED(hr))
     {
         wined3d_mutex_unlock();
@@ -2940,18 +2946,16 @@ static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *ifac
  *****************************************************************************/
 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
 {
-    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
-    HRESULT hr;
-
     TRACE("iface %p, flags %#x.\n", iface, Flags);
 
-    wined3d_mutex_lock();
-    hr = wined3d_surface_get_blt_status(surface->wined3d_surface, Flags);
-    wined3d_mutex_unlock();
-    switch(hr)
+    switch (Flags)
     {
-        case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
-        default:                            return hr;
+        case WINEDDGBS_CANBLT:
+        case WINEDDGBS_ISBLTDONE:
+            return DD_OK;
+
+        default:
+            return DDERR_INVALIDPARAMS;
     }
 }
 
@@ -3114,19 +3118,18 @@ static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWOR
  *****************************************************************************/
 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
 {
-    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
-    HRESULT hr;
-
     TRACE("iface %p, flags %#x.\n", iface, Flags);
 
-    wined3d_mutex_lock();
-    hr = wined3d_surface_get_flip_status(surface->wined3d_surface, Flags);
-    wined3d_mutex_unlock();
+    /* XXX: DDERR_INVALIDSURFACETYPE */
 
-    switch(hr)
+    switch (Flags)
     {
-        case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
-        default:                            return hr;
+        case WINEDDGFS_CANFLIP:
+        case WINEDDGFS_ISFLIPDONE:
+            return DD_OK;
+
+        default:
+            return DDERR_INVALIDPARAMS;
     }
 }
 
@@ -4636,15 +4639,21 @@ static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD
     DDCOLORKEY fixed_color_key;
     HRESULT hr = WINED3D_OK;
 
+    if (flags & DDCKEY_COLORSPACE)
+    {
+        if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
+        {
+            WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
+            return DDERR_NOCOLORKEYHW;
+        }
+        flags &= ~DDCKEY_COLORSPACE;
+    }
+
     wined3d_mutex_lock();
 
     if (color_key)
     {
-        fixed_color_key = *color_key;
-        /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
-        if (fixed_color_key.dwColorSpaceHighValue < fixed_color_key.dwColorSpaceLowValue)
-            fixed_color_key.dwColorSpaceHighValue = fixed_color_key.dwColorSpaceLowValue;
-
+        fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
         switch (flags & ~DDCKEY_COLORSPACE)
         {
             case DDCKEY_DESTBLT:
@@ -5125,8 +5134,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
     {
         DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
 
-        TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
-                src_surface, dst_surface, src_surface->mipmap_level);
+        TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
 
         if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
                            &dst_surface->surface_desc.u4.ddpfPixelFormat))
@@ -5418,7 +5426,7 @@ static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
     ddraw_surface2_PageUnlock,
 };
 
-static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
+static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
 {
     /* IUnknown */
     ddraw_surface1_QueryInterface,
@@ -5935,7 +5943,24 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
 
     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
     {
-        wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
+        /*
+         * The ddraw RGB device allows to use system memory surfaces as rendering target.
+         * This does not cause problems because the RGB device does software rasterization
+         * though it will fail with hardware accelerated ddraw. In order to be partially
+         * compatible with games requesting explicitly the RGB device, we ignore the
+         * specified location and try to create rendering targets in video memory if
+         * possible.
+         */
+        if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
+            SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
+                        WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET,
+                        WINED3D_RTYPE_SURFACE, wined3d_desc.format)))
+        {
+            FIXME("Application wants to create rendering target in system memory, using video memory instead\n");
+            wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
+        }
+        else
+            wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
     }
     else
     {
@@ -6027,6 +6052,20 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
         }
     }
 
+    if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
+            && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKDESTBLT)
+            && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
+            && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKSRCBLT)
+            && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
+    {
+        WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_NOCOLORKEYHW;
+    }
+
     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
         wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
 
@@ -6217,10 +6256,6 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru
     DDSURFACEDESC2 *desc = &surface->surface_desc;
     struct wined3d_resource_desc wined3d_desc;
     unsigned int version = texture->version;
-    UINT row_pitch, slice_pitch;
-    struct wined3d_resource *resource = wined3d_surface_get_resource(wined3d_surface);
-
-    wined3d_resource_get_pitch(resource, &row_pitch, &slice_pitch);
 
     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
@@ -6251,7 +6286,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru
     }
 
     *desc = texture->surface_desc;
-    wined3d_resource_get_desc(resource, &wined3d_desc);
+    wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &wined3d_desc);
     desc->dwWidth = wined3d_desc.width;
     desc->dwHeight = wined3d_desc.height;
     surface->first_attached = surface;
@@ -6261,16 +6296,14 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru
         if (desc->dwFlags & DDSD_LPSURFACE)
             desc->u1.dwLinearSize = ~0u;
         else
-        {
-            desc->u1.dwLinearSize = row_pitch * ((desc->dwHeight + 3) / 4);
-        }
+            desc->u1.dwLinearSize = wined3d_surface_get_pitch(wined3d_surface) * ((desc->dwHeight + 3) / 4);
         desc->dwFlags |= DDSD_LINEARSIZE;
         desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
     }
     else
     {
         if (!(desc->dwFlags & DDSD_LPSURFACE))
-            desc->u1.lPitch = row_pitch;
+            desc->u1.lPitch = wined3d_surface_get_pitch(wined3d_surface);
         desc->dwFlags |= DDSD_PITCH;
         desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
     }
index fd59025..127bc64 100644 (file)
@@ -803,7 +803,8 @@ static void shader_generate_arb_declarations(const struct wined3d_shader *shader
             {
                 DWORD idx = i >> 5;
                 DWORD shift = i & 0x1f;
-                if(reg_maps->constf[idx] & (1 << shift)) highest_constf = i;
+                if (reg_maps->constf[idx] & (1u << shift))
+                    highest_constf = i;
             }
 
             if(use_nv_clip(gl_info) && ctx->target_version >= NV2)
@@ -888,11 +889,14 @@ static void shader_generate_arb_declarations(const struct wined3d_shader *shader
         /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
         shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
                     max_constantsF, max_constantsF - 1);
-    } else {
-        for(i = 0; i < max_constantsF; i++) {
+    }
+    else
+    {
+        for (i = 0; i < max_constantsF; ++i)
+        {
             DWORD idx, mask;
             idx = i >> 5;
-            mask = 1 << (i & 0x1f);
+            mask = 1u << (i & 0x1fu);
             if (!shader_constant_is_local(shader, i) && (reg_maps->constf[idx] & mask))
             {
                 shader_addline(buffer, "PARAM C%d = program.env[%d];\n",i, i);
@@ -1085,7 +1089,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
             }
             else
             {
-                if (ctx->cur_vs_args->super.swizzle_map & (1 << reg->idx[0].offset))
+                if (ctx->cur_vs_args->super.swizzle_map & (1u << reg->idx[0].offset))
                     *is_color = TRUE;
                 sprintf(register_name, "vertex.attrib[%u]", reg->idx[0].offset);
             }
@@ -1424,14 +1428,14 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD
             device = shader->device;
             gl_info = &device->adapter->gl_info;
 
-            if (pshader && priv->cur_ps_args->super.np2_fixup & (1 << sampler_idx)
+            if (pshader && priv->cur_ps_args->super.np2_fixup & (1u << sampler_idx)
                     && gl_info->supported[ARB_TEXTURE_RECTANGLE])
                 tex_type = "RECT";
             else
                 tex_type = "2D";
             if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
             {
-                if (priv->cur_np2fixup_info->super.active & (1 << sampler_idx))
+                if (priv->cur_np2fixup_info->super.active & (1u << sampler_idx))
                 {
                     if (flags) FIXME("Only ordinary sampling from NP2 textures is supported.\n");
                     else np2_fixup = TRUE;
@@ -1977,7 +1981,7 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
     shader_arb_get_dst_param(ins, dst, reg_dest);
 
     /* 1.0-1.4: Use destination register number as texture code.
-       2.0+: Use provided sampler number as texure code. */
+       2.0+: Use provided sampler number as texture code. */
     if (shader_version < WINED3D_SHADER_VERSION(2,0))
         reg_sampler_code = dst->reg.idx[0].offset;
     else
@@ -3218,7 +3222,7 @@ static void vshader_add_footer(struct shader_arb_ctx_priv *priv_ctx,
 
         for (i = 0; i < gl_info->limits.clipplanes; ++i)
         {
-            if (args->clip.boolclip.clipplane_mask & (1 << i))
+            if (args->clip.boolclip.clipplane_mask & (1u << i))
             {
                 shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n",
                                component[cur_clip++], i);
@@ -3808,7 +3812,8 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
                        i, compiled->bumpenvmatconst[bump_const].const_num);
         compiled->numbumpenvmatconsts = bump_const + 1;
 
-        if (!(reg_maps->luminanceparams & (1 << i))) continue;
+        if (!(reg_maps->luminanceparams & (1u << i)))
+            continue;
 
         compiled->luminanceconst[bump_const].const_num = next_local++;
         shader_addline(buffer, "PARAM luminance%d = program.local[%d];\n",
@@ -3818,7 +3823,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     for(i = 0; i < MAX_CONST_I; i++)
     {
         compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
-        if (reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
+        if (reg_maps->integer_constants & (1u << i) && priv_ctx.target_version >= NV2)
         {
             const DWORD *control_values = find_loop_control_values(shader, i);
 
@@ -3874,13 +3879,18 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
         fixup->offset = next_local;
         fixup->super.active = 0;
 
-        for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
-            if (!(map & (1 << i))) continue;
+        for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+        {
+            if (!(map & (1u << i)))
+                continue;
 
-            if (fixup->offset + (cur_fixup_sampler >> 1) < max_lconsts) {
-                fixup->super.active |= (1 << i);
+            if (fixup->offset + (cur_fixup_sampler >> 1) < max_lconsts)
+            {
+                fixup->super.active |= (1u << i);
                 fixup->super.idx[i] = cur_fixup_sampler++;
-            } else {
+            }
+            else
+            {
                 FIXME("No free constant found to load NP2 fixup data into shader. "
                       "Sampling from this texture will probably look wrong.\n");
                 break;
@@ -4261,7 +4271,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
     for(i = 0; i < MAX_CONST_I; i++)
     {
         compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
-        if(reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
+        if (reg_maps->integer_constants & (1u << i) && priv_ctx.target_version >= NV2)
         {
             const DWORD *control_values = find_loop_control_values(shader, i);
 
@@ -4305,7 +4315,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
             const char *one = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ONE);
             for(i = 0; i < MAX_REG_TEXCRD; i++)
             {
-                if (reg_maps->texcoord_mask[i] && reg_maps->texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL)
+                if (reg_maps->u.texcoord_mask[i] && reg_maps->u.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL)
                     shader_addline(buffer, "MOV result.texcoord[%u].w, %s\n", i, one);
             }
         }
@@ -4526,7 +4536,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
     int i;
     WORD int_skip;
 
-    find_ps_compile_args(state, shader, context->stream_info.position_transformed, &args->super, gl_info);
+    find_ps_compile_args(state, shader, context->stream_info.position_transformed, &args->super, context);
 
     /* This forces all local boolean constants to 1 to make them stateblock independent */
     args->bools = shader->reg_maps.local_bool_consts;
@@ -4534,7 +4544,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
     for(i = 0; i < MAX_CONST_B; i++)
     {
         if (state->ps_consts_b[i])
-            args->bools |= ( 1 << i);
+            args->bools |= ( 1u << i);
     }
 
     /* Only enable the clip plane emulation KIL if at least one clipplane is enabled. The KIL instruction
@@ -4556,9 +4566,9 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
         return;
     }
 
-    for(i = 0; i < MAX_CONST_I; i++)
+    for (i = 0; i < MAX_CONST_I; ++i)
     {
-        if(int_skip & (1 << i))
+        if (int_skip & (1u << i))
         {
             args->loop_ctrl[i][0] = 0;
             args->loop_ctrl[i][1] = 0;
@@ -4584,7 +4594,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
     int i;
     WORD int_skip;
 
-    find_vs_compile_args(state, shader, context->stream_info.swizzle_map, &args->super);
+    find_vs_compile_args(state, shader, context->stream_info.swizzle_map, &args->super, d3d_info);
 
     args->clip.boolclip_compare = 0;
     if (use_ps(state))
@@ -4616,7 +4626,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
     for(i = 0; i < MAX_CONST_B; i++)
     {
         if (state->vs_consts_b[i])
-            args->clip.boolclip.bools |= ( 1 << i);
+            args->clip.boolclip.bools |= (1u << i);
     }
 
     args->vertex.samplers[0] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 0];
@@ -4635,7 +4645,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
 
     for(i = 0; i < MAX_CONST_I; i++)
     {
-        if(int_skip & (1 << i))
+        if (int_skip & (1u << i))
         {
             args->loop_ctrl[i][0] = 0;
             args->loop_ctrl[i][1] = 0;
@@ -4822,9 +4832,9 @@ static void shader_arb_disable(void *shader_priv, struct wined3d_context *contex
         priv->last_vs_color_unclamp = FALSE;
     }
 
-    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
-            | (1 << WINED3D_SHADER_TYPE_VERTEX)
-            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+    context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
+            | (1u << WINED3D_SHADER_TYPE_VERTEX)
+            | (1u << WINED3D_SHADER_TYPE_GEOMETRY);
 }
 
 /* Context activation is done by the caller. */
@@ -5153,6 +5163,7 @@ static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct sh
         caps->ps_1x_max_value = 0.0f;
     }
 
+    caps->varying_count = 0;
     caps->wined3d_caps = WINED3D_SHADER_CAP_SRGB_WRITE;
     if (use_nv_clip(gl_info))
         caps->wined3d_caps |= WINED3D_SHADER_CAP_VS_CLIPPING;
@@ -5328,7 +5339,7 @@ static BOOL get_bool_const(const struct wined3d_shader_instruction *ins,
     BOOL vshader = shader_is_vshader_version(reg_maps->shader_version.type);
     const struct wined3d_shader_lconst *constant;
     WORD bools = 0;
-    WORD flag = (1 << idx);
+    WORD flag = (1u << idx);
     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
 
     if (reg_maps->local_bool_consts & flag)
@@ -5360,7 +5371,7 @@ static void get_loop_control_const(const struct wined3d_shader_instruction *ins,
 
     /* Integer constants can either be a local constant, or they can be stored in the shader
      * type specific compile args. */
-    if (reg_maps->local_int_consts & (1 << idx))
+    if (reg_maps->local_int_consts & (1u << idx))
     {
         const struct wined3d_shader_lconst *constant;
 
@@ -5758,8 +5769,9 @@ const struct wined3d_shader_backend_ops arb_program_shader_backend =
 
 /* ARB_fragment_program fixed function pipeline replacement definitions */
 #define ARB_FFP_CONST_TFACTOR           0
-#define ARB_FFP_CONST_COLOR_KEY         ((ARB_FFP_CONST_TFACTOR) + 1)
-#define ARB_FFP_CONST_SPECULAR_ENABLE   ((ARB_FFP_CONST_COLOR_KEY) + 1)
+#define ARB_FFP_CONST_COLOR_KEY_LOW     ((ARB_FFP_CONST_TFACTOR) + 1)
+#define ARB_FFP_CONST_COLOR_KEY_HIGH    ((ARB_FFP_CONST_COLOR_KEY_LOW) + 1)
+#define ARB_FFP_CONST_SPECULAR_ENABLE   ((ARB_FFP_CONST_COLOR_KEY_HIGH) + 1)
 #define ARB_FFP_CONST_CONSTANT(i)       ((ARB_FFP_CONST_SPECULAR_ENABLE) + 1 + i)
 #define ARB_FFP_CONST_BUMPMAT(i)        ((ARB_FFP_CONST_CONSTANT(7)) + 1 + i)
 #define ARB_FFP_CONST_LUMINANCE(i)      ((ARB_FFP_CONST_BUMPMAT(7)) + 1 + i)
@@ -5873,6 +5885,11 @@ static void arbfp_get_caps(const struct wined3d_gl_info *gl_info, struct fragmen
     caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8);
 }
 
+static DWORD arbfp_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
+}
+
 static void state_texfactor_arbfp(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
@@ -6027,7 +6044,7 @@ static void color_key_arbfp(struct wined3d_context *context, const struct wined3
 {
     struct wined3d_device *device = context->swapchain->device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_color float_key;
+    struct wined3d_color float_key[2];
     const struct wined3d_texture *texture = state->textures[0];
 
     if (!texture)
@@ -6043,14 +6060,17 @@ static void color_key_arbfp(struct wined3d_context *context, const struct wined3
             return;
 
         priv = device->shader_priv;
-        priv->pshader_const_dirty[ARB_FFP_CONST_COLOR_KEY] = 1;
-        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_COLOR_KEY + 1);
+        priv->pshader_const_dirty[ARB_FFP_CONST_COLOR_KEY_LOW] = 1;
+        priv->pshader_const_dirty[ARB_FFP_CONST_COLOR_KEY_HIGH] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_COLOR_KEY_HIGH + 1);
     }
 
-    wined3d_format_convert_color_to_float(texture->resource.format, NULL,
-            texture->async.src_blt_color_key.color_space_high_value, &float_key);
-    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY, &float_key.r));
-    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY, &float_key.r)");
+    wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key);
+
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY_LOW, &float_key[0].r));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY_LOW, &float_key[0].r)");
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY_HIGH, &float_key[1].r));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_COLOR_KEY_HIGH, &float_key[1].r)");
 }
 
 static const char *get_argreg(struct wined3d_string_buffer *buffer, DWORD argnum, unsigned int stage, DWORD arg)
@@ -6305,7 +6325,8 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
 
     if (settings->color_key_enabled)
     {
-        shader_addline(&buffer, "PARAM color_key = program.env[%u];\n", ARB_FFP_CONST_COLOR_KEY);
+        shader_addline(&buffer, "PARAM color_key_low = program.env[%u];\n", ARB_FFP_CONST_COLOR_KEY_LOW);
+        shader_addline(&buffer, "PARAM color_key_high = program.env[%u];\n", ARB_FFP_CONST_COLOR_KEY_HIGH);
         tex_read[0] = TRUE;
     }
 
@@ -6489,10 +6510,12 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
 
     if (settings->color_key_enabled)
     {
-        shader_addline(&buffer, "SUB TMP, tex0, color_key;\n");
-        shader_addline(&buffer, "DP4 TMP.b, TMP, TMP;\n");
-        shader_addline(&buffer, "SGE TMP, -TMP.b, 0.0;\n");
-        shader_addline(&buffer, "KIL -TMP;\n");
+        shader_addline(&buffer, "SLT TMP, tex0, color_key_low;\n"); /* below low key */
+        shader_addline(&buffer, "SGE ret, tex0, color_key_high;\n"); /* above high key */
+        shader_addline(&buffer, "ADD TMP, TMP, ret;\n"); /* or */
+        shader_addline(&buffer, "DP4 TMP.b, TMP, TMP;\n"); /* on any channel */
+        shader_addline(&buffer, "SGE TMP, -TMP.b, 0.0;\n"); /* logical not */
+        shader_addline(&buffer, "KIL -TMP;\n"); /* discard if true */
     }
 
     /* Generate the main shader */
@@ -6601,7 +6624,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         }
         else if (use_pshader)
         {
-            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+            context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
         }
         return;
     }
@@ -6655,7 +6678,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         context->last_was_pshader = TRUE;
     }
 
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 /* We can't link the fog states to the fragment state directly since the
@@ -6858,6 +6881,7 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] =
     {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_SPECULARENABLE),             { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            state_arb_specularenable}, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                  { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode         }, WINED3D_GL_EXT_NONE             },
     {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
 };
 
@@ -6873,6 +6897,7 @@ static void arbfp_free_context_data(struct wined3d_context *context)
 const struct fragment_pipeline arbfp_fragment_pipeline = {
     arbfp_enable,
     arbfp_get_caps,
+    arbfp_get_emul_mask,
     arbfp_alloc,
     arbfp_free,
     arbfp_alloc_context_data,
@@ -6897,7 +6922,8 @@ struct arbfp_blit_desc
 };
 
 #define ARBFP_BLIT_PARAM_SIZE 0
-#define ARBFP_BLIT_PARAM_COLOR_KEY 1
+#define ARBFP_BLIT_PARAM_COLOR_KEY_LOW 1
+#define ARBFP_BLIT_PARAM_COLOR_KEY_HIGH 2
 
 struct arbfp_blit_priv
 {
@@ -7582,13 +7608,16 @@ static GLuint arbfp_gen_plain_shader(struct arbfp_blit_priv *priv,
     if (type->use_color_key)
     {
         shader_addline(&buffer, "TEMP color;\n");
-        shader_addline(&buffer, "TEMP compare;\n");
-        shader_addline(&buffer, "PARAM color_key = program.local[%u];\n", ARBFP_BLIT_PARAM_COLOR_KEY);
+        shader_addline(&buffer, "TEMP less, greater;\n");
+        shader_addline(&buffer, "PARAM color_key_low = program.local[%u];\n", ARBFP_BLIT_PARAM_COLOR_KEY_LOW);
+        shader_addline(&buffer, "PARAM color_key_high = program.local[%u];\n", ARBFP_BLIT_PARAM_COLOR_KEY_HIGH);
         shader_addline(&buffer, "TEX color, fragment.texcoord[0], texture[0], %s;\n", tex_target);
-        shader_addline(&buffer, "SUB compare, color, color_key;\n");
-        shader_addline(&buffer, "DP4 compare.r, compare, compare;\n");
-        shader_addline(&buffer, "SGE compare, -compare.r, 0.0;\n");
-        shader_addline(&buffer, "KIL -compare;\n");
+        shader_addline(&buffer, "SLT less, color, color_key_low;\n"); /* below low key */
+        shader_addline(&buffer, "SGE greater, color, color_key_high;\n"); /* above high key */
+        shader_addline(&buffer, "ADD less, less, greater;\n"); /* or */
+        shader_addline(&buffer, "DP4 less.b, less, less;\n"); /* on any channel */
+        shader_addline(&buffer, "SGE less, -less.b, 0.0;\n"); /* logical not */
+        shader_addline(&buffer, "KIL -less;\n"); /* discard if true */
         shader_addline(&buffer, "MOV result.color, color;\n");
     }
     else
@@ -7618,7 +7647,7 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
     struct wine_rb_entry *entry;
     struct arbfp_blit_type type;
     struct arbfp_blit_desc *desc;
-    struct wined3d_color float_color_key;
+    struct wined3d_color float_color_key[2];
 
     if (is_complex_fixup(surface->resource.format->color_fixup))
         fixup = get_complex_fixup(surface->resource.format->color_fixup);
@@ -7719,10 +7748,11 @@ err_out:
     checkGLcall("glProgramLocalParameter4fvARB");
     if (type.use_color_key)
     {
-        wined3d_format_convert_color_to_float(surface->resource.format, NULL,
-                surface->container->async.src_blt_color_key.color_space_high_value, &float_color_key);
+        wined3d_format_get_float_color_key(surface->resource.format, color_key, float_color_key);
+        GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
+                ARBFP_BLIT_PARAM_COLOR_KEY_LOW, &float_color_key[0].r));
         GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
-                ARBFP_BLIT_PARAM_COLOR_KEY, &float_color_key.r));
+                ARBFP_BLIT_PARAM_COLOR_KEY_HIGH, &float_color_key[1].r));
         checkGLcall("glProgramLocalParameter4fvARB");
     }
 
@@ -7836,7 +7866,7 @@ static void arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
          * flip in the blitter, we don't actually need that flip anyway. So we
          * use the surface's texture as scratch texture, and flip the source
          * rectangle instead. */
-        surface_load_fb_texture(src_surface, FALSE);
+        surface_load_fb_texture(src_surface, FALSE, context);
 
         src_rect.top = src_surface->resource.height - src_rect.top;
         src_rect.bottom = src_surface->resource.height - src_rect.bottom;
index 5b4d3eb..cad4e8a 100644 (file)
@@ -1108,6 +1108,7 @@ static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
     {STATE_RENDER(WINED3D_RS_FOGEND),                     { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           atifs_srgbwriteenable   }, WINED3D_GL_EXT_NONE             },
     {STATE_COLOR_KEY,                                     { STATE_COLOR_KEY,                                    state_nop               }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                  { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode         }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
@@ -1304,6 +1305,11 @@ static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragmen
     caps->MaxSimultaneousTextures = 6;
 }
 
+static DWORD atifs_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
+}
+
 static void *atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
 {
     struct atifs_private_data *priv;
@@ -1380,6 +1386,7 @@ static void atifs_free_context_data(struct wined3d_context *context)
 const struct fragment_pipeline atifs_fragment_pipeline = {
     atifs_enable,
     atifs_get_caps,
+    atifs_get_emul_mask,
     atifs_alloc,
     atifs_free,
     atifs_alloc_context_data,
index b39d9c3..f3f2012 100644 (file)
@@ -298,7 +298,7 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct win
     /* Ignore attributes that do not have our vbo. After that check we can be sure that the attribute is
      * there, on nonexistent attribs the vbo is 0.
      */
-    if (!(si->use_map & (1 << attrib_idx))
+    if (!(si->use_map & (1u << attrib_idx))
             || state->streams[attrib->stream_idx].buffer != This)
         return FALSE;
 
@@ -466,9 +466,9 @@ static inline void fixup_d3dcolor(DWORD *dst_color)
      */
 #endif /* STAGING_CSMT */
     *dst_color = 0;
-    *dst_color |= (src_color & 0xff00ff00);         /* Alpha Green */
-    *dst_color |= (src_color & 0x00ff0000) >> 16;   /* Red */
-    *dst_color |= (src_color & 0x000000ff) << 16;   /* Blue */
+    *dst_color |= (src_color & 0xff00ff00u);         /* Alpha Green */
+    *dst_color |= (src_color & 0x00ff0000u) >> 16;   /* Red */
+    *dst_color |= (src_color & 0x000000ffu) << 16;   /* Blue */
 }
 
 static inline void fixup_transformed_pos(float *p)
@@ -1083,7 +1083,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
      *
      * Don't try to solve this by going back to always invalidating changed areas.
      * This won't work if we ever want to support glMapBufferRange mapping with
-     * GL_buffer_storage in the CS.
+     * GL_ARB_buffer_storage in the CS.
      *
      * Also keep in mind that UnLoad can destroy the VBO, so simply creating it
      * on buffer creation won't work either. */
@@ -1222,9 +1222,12 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
         BOOL swvp = device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING;
         if (flags & WINED3D_MAP_DISCARD && !swvp)
         {
-            buffer->ignore_discard = TRUE;
-            wined3d_resource_allocate_sysmem(&buffer->resource);
-            wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory);
+            if (buffer->resource.access_fence)
+            {
+                buffer->ignore_discard = TRUE;
+                wined3d_resource_allocate_sysmem(&buffer->resource);
+                wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory);
+            }
         }
         else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY)) && !buffer->ignore_discard)
         {
@@ -1354,6 +1357,44 @@ static ULONG buffer_resource_decref(struct wined3d_resource *resource)
     return wined3d_buffer_decref(buffer_from_resource(resource));
 }
 
+static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx,
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
+{
+    struct wined3d_buffer *buffer = buffer_from_resource(resource);
+    UINT offset, size;
+
+    if (sub_resource_idx)
+    {
+        WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+        return E_INVALIDARG;
+    }
+
+    if (box)
+    {
+        offset = box->left;
+        size = box->right - box->left;
+    }
+    else
+    {
+        offset = size = 0;
+    }
+
+    map_desc->row_pitch = map_desc->slice_pitch = buffer->desc.byte_width;
+    return wined3d_buffer_map(buffer, offset, size, (BYTE **)&map_desc->data, flags);
+}
+
+static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    if (sub_resource_idx)
+    {
+        WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+        return E_INVALIDARG;
+    }
+
+    wined3d_buffer_unmap(buffer_from_resource(resource));
+    return WINED3D_OK;
+}
+
 #if defined(STAGING_CSMT)
 static void wined3d_buffer_location_invalidated(struct wined3d_resource *resource, DWORD location)
 {
@@ -1367,25 +1408,23 @@ static void wined3d_buffer_load_location(struct wined3d_resource *resource,
     ERR("Not yet implemented.\n");
 }
 
+#endif /* STAGING_CSMT */
 static const struct wined3d_resource_ops buffer_resource_ops =
 {
     buffer_resource_incref,
     buffer_resource_decref,
     buffer_unload,
+    buffer_resource_sub_resource_map,
+    buffer_resource_sub_resource_unmap,
+#if defined(STAGING_CSMT)
     wined3d_buffer_location_invalidated,
     wined3d_buffer_load_location,
-#else  /* STAGING_CSMT */
-static const struct wined3d_resource_ops buffer_resource_ops =
-{
-    buffer_resource_incref,
-    buffer_resource_decref,
-    buffer_unload,
 #endif /* STAGING_CSMT */
 };
 
 static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device,
         UINT size, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, GLenum bind_hint,
-        const char *data, void *parent, const struct wined3d_parent_ops *parent_ops)
+        const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
@@ -1398,6 +1437,12 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
         return WINED3DERR_INVALIDCALL;
     }
 
+    if (data && !data->data)
+    {
+        WARN("Invalid sub-resource data specified.\n");
+        return E_INVALIDARG;
+    }
+
     hr = resource_init(&buffer->resource, device, WINED3D_RTYPE_BUFFER, format,
             WINED3D_MULTISAMPLE_NONE, 0, usage, pool, size, 1, 1, size, parent, parent_ops, &buffer_resource_ops);
     if (FAILED(hr))
@@ -1458,6 +1503,18 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
         buffer->flags |= WINED3D_BUFFER_CREATEBO;
     }
 
+#if defined(STAGING_CSMT)
+    buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps));
+    if (!buffer->maps)
+    {
+        ERR("Out of memory\n");
+        buffer_unload(&buffer->resource);
+        resource_cleanup(&buffer->resource);
+        return E_OUTOFMEMORY;
+    }
+    buffer->maps_size = 1;
+
+#endif /* STAGING_CSMT */
     if (data)
     {
         BYTE *ptr;
@@ -1466,16 +1523,23 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
         if (FAILED(hr))
         {
             ERR("Failed to map buffer, hr %#x\n", hr);
+#if defined(STAGING_CSMT)
+            HeapFree(GetProcessHeap(), 0, buffer->maps);
+#endif /* STAGING_CSMT */
             buffer_unload(&buffer->resource);
             resource_cleanup(&buffer->resource);
             return hr;
         }
 
-        memcpy(ptr, data, size);
+        memcpy(ptr, data->data, size);
 
         wined3d_buffer_unmap(buffer);
     }
 
+#if defined(STAGING_CSMT)
+    if (wined3d_settings.cs_multithreaded)
+        buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
+#else  /* STAGING_CSMT */
     buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps));
     if (!buffer->maps)
     {
@@ -1485,22 +1549,20 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
         return E_OUTOFMEMORY;
     }
     buffer->maps_size = 1;
-
-#if defined(STAGING_CSMT)
-    if (wined3d_settings.cs_multithreaded)
-        buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
-
 #endif /* STAGING_CSMT */
+
     return WINED3D_OK;
 }
 
 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)
+        const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_buffer **buffer)
 {
     struct wined3d_buffer *object;
     HRESULT hr;
 
-    TRACE("device %p, desc %p, data %p, parent %p, buffer %p\n", device, desc, data, parent, buffer);
+    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p\n",
+            device, desc, data, parent, parent_ops, buffer);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
index 6f3d60f..274bedb 100644 (file)
@@ -297,12 +297,12 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ
 static inline DWORD context_generate_rt_mask(GLenum buffer)
 {
     /* Should take care of all the GL_FRONT/GL_BACK/GL_AUXi/GL_NONE... cases */
-    return buffer ? (1 << 31) | buffer : 0;
+    return buffer ? (1u << 31) | buffer : 0;
 }
 
 static inline DWORD context_generate_rt_mask_from_surface(const struct wined3d_surface *target)
 {
-    return (1 << 31) | surface_get_gl_buffer(target);
+    return (1u << 31) | surface_get_gl_buffer(target);
 }
 
 static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context,
@@ -1131,6 +1131,20 @@ void context_release(struct wined3d_context *context)
     }
 }
 
+/* This is used when a context for render target A is active, but a separate context is
+ * needed to access the WGL framebuffer for render target B. Re-acquire a context for rt
+ * A to avoid breaking caller code. */
+void context_restore(struct wined3d_context *context, struct wined3d_surface *restore)
+{
+    if (context->current_rt != restore)
+    {
+        context_release(context);
+        context = context_acquire(restore->resource.device, restore);
+    }
+
+    context_release(context);
+}
+
 static void context_enter(struct wined3d_context *context)
 {
     TRACE("Entering context %p, level %u.\n", context, context->level + 1);
@@ -1163,7 +1177,7 @@ void context_invalidate_state(struct wined3d_context *context, DWORD state)
     context->dirtyArray[context->numDirtyEntries++] = rep;
     idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
     shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
-    context->isStateDirty[idx] |= (1 << shift);
+    context->isStateDirty[idx] |= (1u << shift);
 }
 
 /* This function takes care of wined3d pixel format selection. */
@@ -1172,8 +1186,6 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
         BOOL auxBuffers, BOOL findCompatible)
 {
     int iPixelFormat=0;
-    BYTE redBits, greenBits, blueBits, alphaBits, colorBits;
-    BYTE depthBits=0, stencilBits=0;
     unsigned int current_value;
     unsigned int cfg_count = device->adapter->cfg_count;
     unsigned int i;
@@ -1182,15 +1194,6 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
             device, hdc, debug_d3dformat(color_format->id), debug_d3dformat(ds_format->id),
             auxBuffers, findCompatible);
 
-    if (!getColorBits(color_format, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits))
-    {
-        ERR("Unable to get color bits for format %s (%#x)!\n",
-                debug_d3dformat(color_format->id), color_format->id);
-        return 0;
-    }
-
-    getDepthStencilBits(ds_format, &depthBits, &stencilBits);
-
     current_value = 0;
     for (i = 0; i < cfg_count; ++i)
     {
@@ -1204,17 +1207,17 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
         /* In window mode we need a window drawable format and double buffering. */
         if (!(cfg->windowDrawable && cfg->doubleBuffer))
             continue;
-        if (cfg->redSize < redBits)
+        if (cfg->redSize < color_format->red_size)
             continue;
-        if (cfg->greenSize < greenBits)
+        if (cfg->greenSize < color_format->green_size)
             continue;
-        if (cfg->blueSize < blueBits)
+        if (cfg->blueSize < color_format->blue_size)
             continue;
-        if (cfg->alphaSize < alphaBits)
+        if (cfg->alphaSize < color_format->alpha_size)
             continue;
-        if (cfg->depthSize < depthBits)
+        if (cfg->depthSize < ds_format->depth_size)
             continue;
-        if (stencilBits && cfg->stencilSize != stencilBits)
+        if (ds_format->stencil_size && cfg->stencilSize != ds_format->stencil_size)
             continue;
         /* Check multisampling support. */
         if (cfg->numSamples)
@@ -1223,18 +1226,18 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
         value = 1;
         /* We try to locate a format which matches our requirements exactly. In case of
          * depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
-        if (cfg->depthSize == depthBits)
+        if (cfg->depthSize == ds_format->depth_size)
             value += 1;
-        if (cfg->stencilSize == stencilBits)
+        if (cfg->stencilSize == ds_format->stencil_size)
             value += 2;
-        if (cfg->alphaSize == alphaBits)
+        if (cfg->alphaSize == color_format->alpha_size)
             value += 4;
         /* We like to have aux buffers in backbuffer mode */
         if (auxBuffers && cfg->auxBuffers)
             value += 8;
-        if (cfg->redSize == redBits
-                && cfg->greenSize == greenBits
-                && cfg->blueSize == blueBits)
+        if (cfg->redSize == color_format->red_size
+                && cfg->greenSize == color_format->green_size
+                && cfg->blueSize == color_format->blue_size)
             value += 16;
 
         if (value > current_value)
@@ -1258,10 +1261,11 @@ static int context_choose_pixel_format(const struct wined3d_device *device, HDC
         pfd.nVersion   = 1;
         pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
         pfd.iPixelType = PFD_TYPE_RGBA;
-        pfd.cAlphaBits = alphaBits;
-        pfd.cColorBits = colorBits;
-        pfd.cDepthBits = depthBits;
-        pfd.cStencilBits = stencilBits;
+        pfd.cAlphaBits = color_format->alpha_size;
+        pfd.cColorBits = color_format->red_size + color_format->green_size
+                + color_format->blue_size + color_format->alpha_size;
+        pfd.cDepthBits = ds_format->depth_size;
+        pfd.cStencilBits = ds_format->stencil_size;
         pfd.iLayerType = PFD_MAIN_PLANE;
 
         iPixelFormat = ChoosePixelFormat(hdc, &pfd);
@@ -1456,7 +1460,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     /* Initialize the texture unit mapping to a 1:1 mapping */
     for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s)
     {
-        if (s < gl_info->limits.fragment_samplers)
+        if (s < gl_info->limits.combined_samplers)
         {
             ret->tex_unit_map[s] = s;
             ret->rev_tex_unit_map[s] = s;
@@ -1502,6 +1506,20 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     if (color_format->id == WINED3DFMT_P8_UINT)
         color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
 
+    /* When "always_offscreen" is enabled, we only use the drawable for
+     * presentation blits, and don't do any rendering to it. That means we
+     * don't need depth or stencil buffers, and can mostly ignore the render
+     * target format. This wouldn't necessarily be quite correct for 10bpc
+     * display modes, but we don't currently support those.
+     * Using the same format regardless of the color/depth/stencil targets
+     * makes it much less likely that different wined3d instances will set
+     * conflicting pixel formats. */
+    if (wined3d_settings.always_offscreen)
+    {
+        color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
+        ds_format = wined3d_get_format(gl_info, WINED3DFMT_UNKNOWN);
+    }
+
     /* Try to find a pixel format which matches our requirements. */
     pixel_format = context_choose_pixel_format(device, hdc, color_format, ds_format, auxBuffers, FALSE);
 
@@ -1601,27 +1619,27 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
 
     if (context_debug_output_enabled(gl_info))
     {
-        GL_EXTCALL(glDebugMessageCallbackARB(wined3d_debug_callback, ret));
+        GL_EXTCALL(glDebugMessageCallback(wined3d_debug_callback, ret));
         if (TRACE_ON(d3d_synchronous))
-            gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
-        GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
+            gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+        GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
         if (ERR_ON(d3d))
         {
-            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR_ARB,
+            GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR,
                     GL_DONT_CARE, 0, NULL, GL_TRUE));
         }
         if (FIXME_ON(d3d))
         {
-            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,
+            GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
                     GL_DONT_CARE, 0, NULL, GL_TRUE));
-            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,
+            GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
                     GL_DONT_CARE, 0, NULL, GL_TRUE));
-            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY_ARB,
+            GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY,
                     GL_DONT_CARE, 0, NULL, GL_TRUE));
         }
         if (WARN_ON(d3d_perf))
         {
-            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB,
+            GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE,
                     GL_DONT_CARE, 0, NULL, GL_TRUE));
         }
     }
@@ -1674,6 +1692,15 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);");
 
+    if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    {
+        GLuint vao;
+
+        GL_EXTCALL(glGenVertexArrays(1, &vao));
+        GL_EXTCALL(glBindVertexArray(vao));
+        checkGLcall("creating VAO");
+    }
+
     if (gl_info->supported[ARB_VERTEX_BLEND])
     {
         /* Direct3D always uses n-1 weights for n world matrices and uses
@@ -1735,9 +1762,9 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
     }
     device->shader_backend->shader_init_context_state(ret);
-    ret->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
-            | (1 << WINED3D_SHADER_TYPE_VERTEX)
-            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+    ret->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
+            | (1u << WINED3D_SHADER_TYPE_VERTEX)
+            | (1u << WINED3D_SHADER_TYPE_GEOMETRY);
 
     /* If this happens to be the first context for the device, dummy textures
      * are not created yet. In that case, they will be created (and bound) by
@@ -2035,12 +2062,12 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
 
 static inline BOOL is_rt_mask_onscreen(DWORD rt_mask)
 {
-    return rt_mask & (1 << 31);
+    return rt_mask & (1u << 31);
 }
 
 static inline GLenum draw_buffer_from_rt_mask(DWORD rt_mask)
 {
-    return rt_mask & ~(1 << 31);
+    return rt_mask & ~(1u << 31);
 }
 
 /* Context activation is done by the caller. */
@@ -2181,29 +2208,21 @@ static void context_set_render_offscreen(struct wined3d_context *context, BOOL o
 static BOOL match_depth_stencil_format(const struct wined3d_format *existing,
         const struct wined3d_format *required)
 {
-    BYTE existing_depth, existing_stencil, required_depth, required_stencil;
-
     if (existing == required)
         return TRUE;
     if ((existing->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT)
             != (required->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT))
         return FALSE;
-
-    getDepthStencilBits(existing, &existing_depth, &existing_stencil);
-    getDepthStencilBits(required, &required_depth, &required_stencil);
-
-    if(existing_depth < required_depth) return FALSE;
-    /* If stencil bits are used the exact amount is required - otherwise wrapping
-     * won't work correctly */
-    if(required_stencil && required_stencil != existing_stencil) return FALSE;
+    if (existing->depth_size < required->depth_size)
+        return FALSE;
+    /* If stencil bits are used the exact amount is required - otherwise
+     * wrapping won't work correctly. */
+    if (required->stencil_size && required->stencil_size != existing->stencil_size)
+        return FALSE;
     return TRUE;
 }
 
-#if defined(STAGING_CSMT)
 /* Context activation is done by the caller. */
-#else  /* STAGING_CSMT */
-/* The caller provides a context */
-#endif /* STAGING_CSMT */
 static void context_validate_onscreen_formats(struct wined3d_context *context,
         const struct wined3d_rendertarget_view *depth_stencil)
 {
@@ -2235,7 +2254,7 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *conte
     else
         return context_generate_rt_mask(context->offscreenBuffer);
 #else  /* STAGING_CSMT */
-    surface_load_location(context->current_rt, WINED3D_LOCATION_TEXTURE_RGB);
+    surface_load_location(context->current_rt, context, WINED3D_LOCATION_TEXTURE_RGB);
     swapchain->render_to_fbo = TRUE;
     swapchain_update_draw_bindings(swapchain);
     context_set_render_offscreen(context, TRUE);
@@ -2352,7 +2371,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
                 {
                     context->blit_targets[i] = wined3d_rendertarget_view_get_surface(rts[i]);
                     if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
-                        rt_mask |= (1 << i);
+                        rt_mask |= (1u << i);
                 }
                 while (i < context->gl_info->limits.buffers)
                 {
@@ -2396,7 +2415,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
         for (i = 0; i < rt_count; ++i)
         {
             if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
-                rt_mask |= (1 << i);
+                rt_mask |= (1u << i);
         }
     }
     else
@@ -2471,9 +2490,9 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
     i = 0;
     while (rt_mask_bits)
     {
-        rt_mask_bits &= ~(1 << i);
+        rt_mask_bits &= ~(1u << i);
         if (!rts[i] || rts[i]->format->id == WINED3DFMT_NULL)
-            rt_mask &= ~(1 << i);
+            rt_mask &= ~(1u << i);
 
         i++;
     }
@@ -2533,6 +2552,7 @@ static void context_map_stage(struct wined3d_context *context, DWORD stage, DWOR
     DWORD i = context->rev_tex_unit_map[unit];
     DWORD j = context->tex_unit_map[stage];
 
+    TRACE("Mapping stage %u to unit %u.\n", stage, unit);
     context->tex_unit_map[stage] = unit;
     if (i != WINED3D_UNMAPPED_STAGE && i != stage)
         context->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
@@ -2579,11 +2599,11 @@ static void context_update_fixed_function_usage_map(struct wined3d_context *cont
                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG1)
                 || ((alpha_arg3 == WINED3DTA_TEXTURE)
                     && (alpha_op == WINED3D_TOP_MULTIPLY_ADD || alpha_op == WINED3D_TOP_LERP)))
-            context->fixed_function_usage_map |= (1 << i);
+            context->fixed_function_usage_map |= (1u << i);
 
         if ((color_op == WINED3D_TOP_BUMPENVMAP || color_op == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
                 && i < MAX_TEXTURES - 1)
-            context->fixed_function_usage_map |= (1 << (i + 1));
+            context->fixed_function_usage_map |= (1u << (i + 1));
     }
 
     if (i < context->lowest_disabled_stage)
@@ -2607,11 +2627,16 @@ static void context_update_fixed_function_usage_map(struct wined3d_context *cont
 static void context_map_fixed_function_samplers(struct wined3d_context *context,
         const struct wined3d_state *state)
 {
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     unsigned int i, tex;
     WORD ffu_map;
-    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
 
     context_update_fixed_function_usage_map(context, state);
+
+    if (gl_info->limits.combined_samplers >= MAX_COMBINED_SAMPLERS)
+        return;
+
     ffu_map = context->fixed_function_usage_map;
 
     if (d3d_info->limits.ffp_textures == d3d_info->limits.ffp_blend_stages
@@ -2652,10 +2677,14 @@ static void context_map_fixed_function_samplers(struct wined3d_context *context,
 
 static void context_map_psamplers(struct wined3d_context *context, const struct wined3d_state *state)
 {
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_shader_resource_info *resource_info =
             state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_info;
     unsigned int i;
-    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+
+    if (gl_info->limits.combined_samplers >= MAX_COMBINED_SAMPLERS)
+        return;
 
     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
     {
@@ -2670,8 +2699,7 @@ static void context_map_psamplers(struct wined3d_context *context, const struct
 }
 
 static BOOL context_unit_free_for_vs(const struct wined3d_context *context,
-        const struct wined3d_shader_resource_info *ps_resource_info,
-        const struct wined3d_shader_resource_info *vs_resource_info, DWORD unit)
+        const struct wined3d_shader_resource_info *ps_resource_info, DWORD unit)
 {
     DWORD current_mapping = context->rev_tex_unit_map[unit];
 
@@ -2686,15 +2714,14 @@ static BOOL context_unit_free_for_vs(const struct wined3d_context *context,
         if (!ps_resource_info)
         {
             /* No pixel shader, check fixed function */
-            return current_mapping >= MAX_TEXTURES || !(context->fixed_function_usage_map & (1 << current_mapping));
+            return current_mapping >= MAX_TEXTURES || !(context->fixed_function_usage_map & (1u << current_mapping));
         }
 
         /* Pixel shader, check the shader's sampler map */
         return !ps_resource_info[current_mapping].type;
     }
 
-    /* Used by a vertex sampler */
-    return !vs_resource_info[current_mapping - MAX_FRAGMENT_SAMPLERS].type;
+    return TRUE;
 }
 
 static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, const struct wined3d_state *state)
@@ -2706,6 +2733,9 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons
     int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
     int i;
 
+    if (gl_info->limits.combined_samplers >= MAX_COMBINED_SAMPLERS)
+        return;
+
     /* Note that we only care if a resource is used or not, not the
      * resource's specific type. Otherwise we'd need to call
      * shader_update_samplers() here for 1.x pixelshaders. */
@@ -2717,18 +2747,15 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons
         DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
         if (vs_resource_info[i].type)
         {
-            if (context->tex_unit_map[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
-            {
-                /* Already mapped somewhere */
-                continue;
-            }
-
             while (start >= 0)
             {
-                if (context_unit_free_for_vs(context, ps_resource_info, vs_resource_info, start))
+                if (context_unit_free_for_vs(context, ps_resource_info, start))
                 {
-                    context_map_stage(context, vsampler_idx, start);
-                    context_invalidate_state(context, STATE_SAMPLER(vsampler_idx));
+                    if (context->tex_unit_map[vsampler_idx] != start)
+                    {
+                        context_map_stage(context, vsampler_idx, start);
+                        context_invalidate_state(context, STATE_SAMPLER(vsampler_idx));
+                    }
 
                     --start;
                     break;
@@ -2736,6 +2763,8 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons
 
                 --start;
             }
+            if (context->tex_unit_map[vsampler_idx] == WINED3D_UNMAPPED_STAGE)
+                WARN("Couldn't find a free texture unit for vertex sampler %u.\n", i);
         }
     }
 }
@@ -2744,13 +2773,12 @@ static void context_update_tex_unit_map(struct wined3d_context *context, const s
 {
     BOOL vs = use_vs(state);
     BOOL ps = use_ps(state);
-    /*
-     * Rules are:
-     * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
-     * that would be really messy and require shader recompilation
-     * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
-     * to be reset. Because of that try to work with a 1:1 mapping as much as possible
-     */
+
+    /* Try to go for a 1:1 mapping of the samplers when possible. Pixel shaders
+     * need a 1:1 map at the moment.
+     * When the mapping of a stage is changed, sampler and ALL texture stage
+     * states have to be reset. */
+
     if (ps)
         context_map_psamplers(context, state);
     else
@@ -2910,9 +2938,9 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
             if (!context->gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
                     && element->format->id == WINED3DFMT_B8G8R8A8_UNORM)
             {
-                stream_info->swizzle_map |= 1 << idx;
+                stream_info->swizzle_map |= 1u << idx;
             }
-            stream_info->use_map |= 1 << idx;
+            stream_info->use_map |= 1u << idx;
         }
     }
 }
@@ -2994,9 +3022,9 @@ static void context_update_stream_info(struct wined3d_context *context, const st
     }
     else
     {
-        WORD slow_mask = (1 << WINED3D_FFP_PSIZE);
+        WORD slow_mask = -!d3d_info->ffp_generic_attributes & (1u << WINED3D_FFP_PSIZE);
         slow_mask |= -!gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
-                & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
+                & ((1u << WINED3D_FFP_DIFFUSE) | (1u << WINED3D_FFP_SPECULAR));
 
         if (((stream_info->position_transformed && !d3d_info->xyzrhw)
                 || (stream_info->use_map & slow_mask)) && !stream_info->all_vbo)
@@ -3055,6 +3083,42 @@ static void context_preload_textures(struct wined3d_context *context, const stru
     }
 }
 
+static void context_load_shader_resources(struct wined3d_context *context, const struct wined3d_state *state)
+{
+    struct wined3d_shader_sampler_map_entry *entry;
+    struct wined3d_shader_resource_view *view;
+    struct wined3d_shader *shader;
+    unsigned int i, j;
+
+    for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
+    {
+        if (!(shader = state->shader[i]))
+            continue;
+
+        for (j = 0; j < WINED3D_MAX_CBS; ++j)
+        {
+            if (state->cb[i][j])
+                buffer_internal_preload(state->cb[i][j], context, state);
+        }
+
+        for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
+        {
+            entry = &shader->reg_maps.sampler_map.entries[j];
+
+            if (!(view = state->shader_resource_view[i][entry->resource_idx]))
+            {
+                WARN("No resource view bound at index %u, %u.\n", i, entry->resource_idx);
+                continue;
+            }
+
+            if (view->resource->type == WINED3D_RTYPE_BUFFER)
+                buffer_internal_preload(buffer_from_resource(view->resource), context, state);
+            else
+                wined3d_texture_load(wined3d_texture_from_resource(view->resource), context, FALSE);
+        }
+    }
+}
+
 static void context_bind_shader_resources(struct wined3d_context *context, const struct wined3d_state *state)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -3113,7 +3177,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
             }
 
             texture = wined3d_texture_from_resource(view->resource);
-            wined3d_texture_load(texture, context, FALSE);
             context_active_texture(context, gl_info, shader_types[i].base_idx + entry->bind_idx);
             wined3d_texture_bind(texture, context, FALSE);
 
@@ -3137,7 +3200,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
     const struct StateEntry *state_table = context->state_table;
     const struct wined3d_fb_state *fb = state->fb;
 #endif /* STAGING_CSMT */
-    unsigned int i, j;
+    unsigned int i;
     WORD map;
 
     if (!context_validate_rt_config(context->gl_info->limits.buffers,
@@ -3154,6 +3217,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
      * updating a resource location. */
     context_update_tex_unit_map(context, state);
     context_preload_textures(context, state);
+    context_load_shader_resources(context, state);
     /* TODO: Right now the dependency on the vertex shader is necessary
      * since context_stream_info_from_declaration depends on the reg_maps of
      * the current VS but maybe it's possible to relax the coupling in some
@@ -3188,21 +3252,12 @@ 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];
         DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
         BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
-        context->isStateDirty[idx] &= ~(1 << shift);
+        context->isStateDirty[idx] &= ~(1u << shift);
         state_table[rep].apply(context, state, rep);
     }
 
index dd44cfa..3237b41 100644 (file)
@@ -99,6 +99,8 @@ enum wined3d_cs_op
     WINED3D_CS_OP_DELETE_GL_CONTEXTS,
     WINED3D_CS_OP_GETDC,
     WINED3D_CS_OP_RELEASEDC,
+    WINED3D_CS_OP_SAMPLER_DESTROY,
+    WINED3D_CS_OP_UPDATE_SUB_RESOURCE,
     WINED3D_CS_OP_STOP,
 };
 
@@ -615,6 +617,21 @@ struct wined3d_cs_releasedc
     struct wined3d_surface *surface;
 };
 
+struct wined3d_cs_sampler_destroy
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_sampler *sampler;
+};
+
+struct wined3d_cs_update_sub_resource
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_resource *resource;
+    unsigned int sub_resource_idx, row_pitch, depth_pitch;
+    const struct wined3d_box *box;
+    const void *data;
+};
+
 static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size)
 {
     LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1);
@@ -772,7 +789,7 @@ static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
 
     if (op->flags & WINED3DCLEAR_TARGET)
     {
-        for (i = 0; i < sizeof(cs->state.fb.render_targets) / sizeof(*cs->state.fb.render_targets); i++)
+        for (i = 0; i < device->adapter->gl_info.limits.buffers; i++)
         {
             if (cs->state.fb.render_targets[i])
                 wined3d_resource_dec_fence(cs->state.fb.render_targets[i]->resource);
@@ -804,7 +821,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *
 
     if (flags & WINED3DCLEAR_TARGET)
     {
-        for (i = 0; i < sizeof(state->fb.render_targets) / sizeof(*state->fb.render_targets); i++)
+        for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; i++)
         {
             if (state->fb.render_targets[i])
                 wined3d_resource_inc_fence(state->fb.render_targets[i]->resource);
@@ -875,7 +892,7 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
         if (cs->state.textures[i])
             wined3d_resource_dec_fence(&cs->state.textures[i]->resource);
     }
-    for (i = 0; i < sizeof(cs->state.fb.render_targets) / sizeof(*cs->state.fb.render_targets); i++)
+    for (i = 0; i < gl_info->limits.buffers; i++)
     {
         if (cs->state.fb.render_targets[i] && wined3d_cs_colorwrite_enabled(&cs->state, i))
             wined3d_resource_dec_fence(cs->state.fb.render_targets[i]->resource);
@@ -919,7 +936,7 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun
         if (state->textures[i])
             wined3d_resource_inc_fence(&state->textures[i]->resource);
     }
-    for (i = 0; i < sizeof(state->fb.render_targets) / sizeof(*state->fb.render_targets); i++)
+    for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; i++)
     {
         if (state->fb.render_targets[i] && wined3d_cs_colorwrite_enabled(state, i))
             wined3d_resource_inc_fence(state->fb.render_targets[i]->resource);
@@ -1034,7 +1051,7 @@ static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const
             surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height);
             if (prev_surface == cs->onscreen_depth_stencil)
             {
-                wined3d_surface_decref(cs->onscreen_depth_stencil);
+                wined3d_texture_decref(cs->onscreen_depth_stencil->container);
                 cs->onscreen_depth_stencil = NULL;
             }
         }
@@ -1050,7 +1067,8 @@ static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
-    else if (prev && prev->format->depth_size != op->view->format->depth_size)
+    else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT)
+            != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT))
     {
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
@@ -1712,7 +1730,7 @@ static UINT wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
 
     if (op->set)
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.dst_blt_color_key = op->color_key;
@@ -1744,7 +1762,7 @@ static UINT wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
     }
     else
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
@@ -1938,12 +1956,6 @@ static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data)
         object->OriginalIndex = light_idx;
     }
 
-    object->OriginalParms = op->light.OriginalParms;
-    memcpy(&object->position, &op->light.position, sizeof(object->position));
-    memcpy(&object->direction, &op->light.direction, sizeof(object->direction));
-    object->exponent = op->light.exponent;
-    object->cutoff = op->light.cutoff;
-
     /* Update the live definitions if the light is currently assigned a glIndex. */
     if (object->glIndex != -1)
     {
@@ -1952,6 +1964,12 @@ static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data)
         device_invalidate_state(cs->device, STATE_ACTIVELIGHT(object->glIndex));
     }
 
+    object->OriginalParms = op->light.OriginalParms;
+    object->position = op->light.position;
+    object->direction = op->light.direction;
+    object->exponent = op->light.exponent;
+    object->cutoff = op->light.cutoff;
+
     return sizeof(*op);
 }
 
@@ -2815,6 +2833,106 @@ void wined3d_cs_emit_releasedc(struct wined3d_cs *cs, struct wined3d_surface *su
     cs->ops->finish(cs);
 }
 
+static UINT wined3d_cs_exec_sampler_destroy(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_sampler_destroy *op = data;
+
+    wined3d_sampler_destroy(op->sampler);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_sampler_destroy(struct wined3d_cs *cs, struct wined3d_sampler *sampler)
+{
+    struct wined3d_cs_sampler_destroy *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SAMPLER_DESTROY;
+    op->sampler = sampler;
+
+    cs->ops->submit(cs, sizeof(*op));
+}
+
+static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_update_sub_resource *op = data;
+
+    struct wined3d_resource *sub_resource;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_const_bo_address addr;
+    struct wined3d_context *context;
+    struct wined3d_texture *texture;
+    struct wined3d_surface *surface;
+    POINT dst_point;
+    RECT src_rect;
+
+    texture = wined3d_texture_from_resource(op->resource);
+    sub_resource = wined3d_texture_get_sub_resource(texture, op->sub_resource_idx);
+    surface = surface_from_resource(sub_resource);
+
+    src_rect.left = 0;
+    src_rect.top = 0;
+    if (op->box)
+    {
+        src_rect.right = op->box->right - op->box->left;
+        src_rect.bottom = op->box->bottom - op->box->top;
+        dst_point.x = op->box->left;
+        dst_point.y = op->box->top;
+    }
+    else
+    {
+        src_rect.right = sub_resource->width;
+        src_rect.bottom = sub_resource->height;
+        dst_point.x = 0;
+        dst_point.y = 0;
+    }
+
+    addr.buffer_object = 0;
+    addr.addr = op->data;
+
+    context = context_acquire(cs->device, NULL);
+    gl_info = context->gl_info;
+
+    /* Only load the surface for partial updates. */
+    if (!dst_point.x && !dst_point.y && src_rect.right == sub_resource->width
+            && src_rect.bottom == sub_resource->height)
+        wined3d_texture_prepare_texture(texture, context, FALSE);
+    else
+        wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
+
+    wined3d_surface_upload_data(surface, gl_info, op->resource->format,
+            &src_rect, op->row_pitch, &dst_point, FALSE, &addr);
+
+    context_release(context);
+
+    wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
+        unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
+        unsigned int depth_pitch)
+{
+    struct wined3d_cs_update_sub_resource *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE;
+    op->resource = resource;
+    op->sub_resource_idx = sub_resource_idx;
+    op->box = box;
+    op->data = data;
+    op->row_pitch = row_pitch;
+    op->depth_pitch = depth_pitch;
+
+    cs->ops->submit(cs, sizeof(*op));
+    /* The data pointer may go away, need to wait until the data is read. Copying the data may be faster.
+     * Don't forget to copy box as well in this case. */
+    cs->ops->finish(cs);
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -3000,7 +3118,7 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const
             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);
+                wined3d_texture_decref(device->onscreen_depth_stencil->container);
                 device->onscreen_depth_stencil = NULL;
             }
         }
@@ -3016,7 +3134,8 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
-    else if (prev && prev->format->depth_size != op->view->format->depth_size)
+    else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT)
+            != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT))
     {
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
@@ -3472,7 +3591,7 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
 
     if (op->set)
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.dst_blt_color_key = op->color_key;
@@ -3504,7 +3623,7 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
     }
     else
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
@@ -3659,6 +3778,8 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_DELETE_GL_CONTEXTS         */ wined3d_cs_exec_delete_gl_contexts,
     /* WINED3D_CS_OP_GETDC                      */ wined3d_cs_exec_getdc,
     /* WINED3D_CS_OP_RELEASEDC                  */ wined3d_cs_exec_releasedc,
+    /* WINED3D_CS_OP_SAMPLER_DESTROY            */ wined3d_cs_exec_sampler_destroy,
+    /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE        */ wined3d_cs_exec_update_sub_resource,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
@@ -3831,10 +3952,10 @@ void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs,
         surface_modify_ds_location(cs->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB,
                 cs->onscreen_depth_stencil->ds_current_size.cx,
                 cs->onscreen_depth_stencil->ds_current_size.cy);
-        wined3d_surface_decref(cs->onscreen_depth_stencil);
+        wined3d_texture_decref(cs->onscreen_depth_stencil->container);
     }
     cs->onscreen_depth_stencil = depth_stencil;
-    wined3d_surface_incref(cs->onscreen_depth_stencil);
+    wined3d_texture_incref(cs->onscreen_depth_stencil->container);
 }
 
 static inline void poll_queries(struct wined3d_cs *cs)
index 9637bd3..67f2e74 100644 (file)
@@ -201,10 +201,10 @@ void device_switch_onscreen_ds(struct wined3d_device *device,
         surface_modify_ds_location(device->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB,
                 device->onscreen_depth_stencil->ds_current_size.cx,
                 device->onscreen_depth_stencil->ds_current_size.cy);
-        wined3d_surface_decref(device->onscreen_depth_stencil);
+        wined3d_texture_decref(device->onscreen_depth_stencil->container);
     }
     device->onscreen_depth_stencil = depth_stencil;
-    wined3d_surface_incref(device->onscreen_depth_stencil);
+    wined3d_texture_incref(device->onscreen_depth_stencil->container);
 }
 
 #endif /* STAGING_CSMT */
@@ -302,7 +302,6 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     unsigned int i;
     RECT ds_rect;
 
-#if defined(STAGING_CSMT)
     context = context_acquire(device, target);
     if (!context->valid)
     {
@@ -312,7 +311,6 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     }
     gl_info = context->gl_info;
 
-#endif /* STAGING_CSMT */
     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
      * for the cleared parts, and the untouched parts.
@@ -329,23 +327,12 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
             if (rt)
 #if defined(STAGING_CSMT)
                 wined3d_resource_load_location(&rt->resource, context, rt->container->resource.draw_binding);
-        }
-    }
 #else  /* STAGING_CSMT */
-                surface_load_location(rt, rt->container->resource.draw_binding);
+                surface_load_location(rt, context, rt->container->resource.draw_binding);
+#endif /* STAGING_CSMT */
         }
     }
 
-    context = context_acquire(device, target);
-    if (!context->valid)
-    {
-        context_release(context);
-        WARN("Invalid context, skipping clear.\n");
-        return;
-    }
-    gl_info = context->gl_info;
-#endif /* STAGING_CSMT */
-
     if (target)
     {
         render_offscreen = context->render_offscreen;
@@ -1126,7 +1113,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     {
         surface = device->cs->onscreen_depth_stencil;
         device->cs->onscreen_depth_stencil = NULL;
-        wined3d_surface_decref(surface);
+        wined3d_texture_decref(surface->container);
     }
 
     state_unbind_resources(&device->state);
@@ -1144,6 +1131,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
         wined3d_cs_emit_evict_resource(device->cs, resource);
     }
 
+    wine_rb_clear(&device->samplers, device_free_sampler, NULL);
+
+    /* FIXME: Is this in the right place??? */
     wined3d_cs_emit_delete_opengl_contexts(device->cs, device->swapchains[0]);
 
 #else  /* STAGING_CSMT */
@@ -1195,7 +1185,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     {
         surface = device->onscreen_depth_stencil;
         device->onscreen_depth_stencil = NULL;
-        wined3d_surface_decref(surface);
+        wined3d_texture_decref(surface->container);
     }
 
     if (device->fb.depth_stencil)
@@ -1353,7 +1343,8 @@ struct wined3d_buffer * CDECL wined3d_device_get_stream_output(struct wined3d_de
         return NULL;
     }
 
-    *offset = device->state.stream_output[idx].offset;
+    if (offset)
+        *offset = device->state.stream_output[idx].offset;
     return device->state.stream_output[idx].buffer;
 }
 
@@ -1381,7 +1372,7 @@ HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UI
     prev_buffer = stream->buffer;
 
     if (device->recording)
-        device->recording->changed.streamSource |= 1 << stream_idx;
+        device->recording->changed.streamSource |= 1u << stream_idx;
 
     if (prev_buffer == buffer
             && stream->stride == stride
@@ -1396,10 +1387,9 @@ HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UI
     {
         stream->stride = stride;
         stream->offset = offset;
+        wined3d_buffer_incref(buffer);
     }
 
-    if (buffer)
-        wined3d_buffer_incref(buffer);
     if (!device->recording)
         wined3d_cs_emit_set_stream_source(device->cs, stream_idx, buffer, offset, stride);
     if (prev_buffer)
@@ -1463,7 +1453,7 @@ HRESULT CDECL wined3d_device_set_stream_source_freq(struct wined3d_device *devic
     stream->frequency = divider & 0x7fffff;
 
     if (device->recording)
-        device->recording->changed.streamFreq |= 1 << stream_idx;
+        device->recording->changed.streamFreq |= 1u << stream_idx;
     else if (stream->frequency != old_freq || stream->flags != old_flags)
         wined3d_cs_emit_set_stream_source_freq(device->cs, stream_idx, stream->frequency, stream->flags);
 
@@ -1499,7 +1489,7 @@ void CDECL wined3d_device_set_transform(struct wined3d_device *device,
     if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
-        device->recording->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
+        device->recording->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
         device->update_state->transforms[d3dts] = *matrix;
         return;
     }
@@ -1905,7 +1895,7 @@ HRESULT CDECL wined3d_device_set_clip_plane(struct wined3d_device *device,
     }
 
     if (device->recording)
-        device->recording->changed.clipplane |= 1 << plane_idx;
+        device->recording->changed.clipplane |= 1u << plane_idx;
 
     if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane)))
     {
@@ -2108,7 +2098,7 @@ void CDECL wined3d_device_set_render_state(struct wined3d_device *device,
     if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
-        device->recording->changed.renderState[state >> 5] |= 1 << (state & 0x1f);
+        device->recording->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
         return;
     }
 
@@ -2156,7 +2146,7 @@ void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device,
     if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
-        device->recording->changed.samplerState[sampler_idx] |= 1 << state;
+        device->recording->changed.samplerState[sampler_idx] |= 1u << state;
         return;
     }
 
@@ -2442,7 +2432,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device,
     if (device->recording)
     {
         for (i = start_register; i < count + start_register; ++i)
-            device->recording->changed.vertexShaderConstantsB |= (1 << i);
+            device->recording->changed.vertexShaderConstantsB |= (1u << i);
     }
     else
     {
@@ -2494,7 +2484,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device,
     if (device->recording)
     {
         for (i = start_register; i < count + start_register; ++i)
-            device->recording->changed.vertexShaderConstantsI |= (1 << i);
+            device->recording->changed.vertexShaderConstantsI |= (1u << i);
     }
     else
     {
@@ -2691,7 +2681,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device,
     if (device->recording)
     {
         for (i = start_register; i < count + start_register; ++i)
-            device->recording->changed.pixelShaderConstantsB |= (1 << i);
+            device->recording->changed.pixelShaderConstantsB |= (1u << i);
     }
     else
     {
@@ -2743,7 +2733,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device,
     if (device->recording)
     {
         for (i = start_register; i < count + start_register; ++i)
-            device->recording->changed.pixelShaderConstantsI |= (1 << i);
+            device->recording->changed.pixelShaderConstantsI |= (1u << i);
     }
     else
     {
@@ -2931,12 +2921,12 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
     DWORD numTextures;
     HRESULT hr;
 
-    if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL))
+    if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL))
     {
         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
     }
 
-    if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION)))
+    if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION)))
     {
         ERR("Source has no position mask\n");
         return WINED3DERR_INVALIDCALL;
@@ -3129,7 +3119,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
         {
             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
             const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride);
-            if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE)))
+            if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE)))
             {
                 static BOOL warned = FALSE;
 
@@ -3152,7 +3142,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
             /* What's the color value in the feedback buffer? */
             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
             const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride);
-            if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR)))
+            if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR)))
             {
                 static BOOL warned = FALSE;
 
@@ -3174,7 +3164,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
         {
             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
             const float *tex_coord = (const float *)(element->data.addr + i * element->stride);
-            if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index))))
+            if (!(stream_info->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + tex_index))))
             {
                 ERR("No source texture, but destination requests one\n");
                 dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
@@ -3284,7 +3274,7 @@ void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
     if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
-        device->recording->changed.textureState[stage] |= 1 << state;
+        device->recording->changed.textureState[stage] |= 1u << state;
         return;
     }
 
@@ -3337,7 +3327,7 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
     }
 
     if (device->recording)
-        device->recording->changed.textures |= 1 << stage;
+        device->recording->changed.textures |= 1u << stage;
 
     prev = device->update_state->textures[stage];
     TRACE("Previous texture %p.\n", prev);
@@ -3377,22 +3367,6 @@ struct wined3d_texture * CDECL wined3d_device_get_texture(const struct wined3d_d
     return device->state.textures[stage];
 }
 
-HRESULT CDECL wined3d_device_get_back_buffer(const struct wined3d_device *device, UINT swapchain_idx,
-        UINT backbuffer_idx, enum wined3d_backbuffer_type backbuffer_type, struct wined3d_surface **backbuffer)
-{
-    struct wined3d_swapchain *swapchain;
-
-    TRACE("device %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
-            device, swapchain_idx, backbuffer_idx, backbuffer_type, backbuffer);
-
-    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
-        return WINED3DERR_INVALIDCALL;
-
-    if (!(*backbuffer = wined3d_swapchain_get_back_buffer(swapchain, backbuffer_idx, backbuffer_type)))
-        return WINED3DERR_INVALIDCALL;
-    return WINED3D_OK;
-}
-
 HRESULT CDECL wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps)
 {
     TRACE("device %p, caps %p.\n", device, caps);
@@ -3504,24 +3478,6 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device)
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_device_present(const struct wined3d_device *device, const RECT *src_rect,
-        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region, DWORD flags)
-{
-    UINT i;
-
-    TRACE("device %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
-            device, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
-            dst_window_override, dirty_region, flags);
-
-    for (i = 0; i < device->swapchain_count; ++i)
-    {
-        wined3d_swapchain_present(device->swapchains[i], src_rect,
-                dst_rect, dst_window_override, dirty_region, flags);
-    }
-
-    return WINED3D_OK;
-}
-
 HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_count,
         const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
 {
@@ -3744,6 +3700,7 @@ static void device_update_volume(struct wined3d_context *context,
     /* Only a prepare, since we're uploading the entire volume. */
     wined3d_texture_prepare_texture(dst_volume->container, context, FALSE);
     wined3d_texture_bind_and_dirtify(dst_volume->container, context, FALSE);
+
     wined3d_resource_get_memory(&src_volume->resource, src_volume->resource.map_binding, &data);
     wined3d_volume_upload_data(dst_volume, context, wined3d_const_bo_address(&data));
     wined3d_resource_invalidate_location(&dst_volume->resource, ~WINED3D_LOCATION_TEXTURE_RGB);
@@ -3963,6 +3920,11 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
         WARN("Destination texture not in WINED3D_POOL_DEFAULT, returning WINED3DERR_INVALIDCALL.\n");
         return WINED3DERR_INVALIDCALL;
     }
+    if (dst_texture->resource.format != src_texture->resource.format)
+    {
+        WARN("Formats do not match, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
 
     /* Verify that the source and destination textures are the same type. */
     type = src_texture->resource.type;
@@ -3996,19 +3958,6 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_device_get_front_buffer_data(const struct wined3d_device *device,
-        UINT swapchain_idx, struct wined3d_surface *dst_surface)
-{
-    struct wined3d_swapchain *swapchain;
-
-    TRACE("device %p, swapchain_idx %u, dst_surface %p.\n", device, swapchain_idx, dst_surface);
-
-    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
-        return WINED3DERR_INVALIDCALL;
-
-    return wined3d_swapchain_get_front_buffer_data(swapchain, dst_surface);
-}
-
 HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes)
 {
     const struct wined3d_state *state = &device->state;
@@ -4153,6 +4102,8 @@ float CDECL wined3d_device_get_npatch_mode(const struct wined3d_device *device)
     return 0.0f;
 }
 
+/* FIXME: Callers should probably use wined3d_device_update_sub_resource()
+ * instead. */
 HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
         struct wined3d_surface *src_surface, const RECT *src_rect,
         struct wined3d_surface *dst_surface, const POINT *dst_point)
@@ -4224,14 +4175,16 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    if ((src_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(src_surface, src_rect))
+    if ((src_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+            && !surface_check_block_align_rect(src_surface, src_rect))
     {
         WARN("Source rectangle not block-aligned.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
     SetRect(&dst_rect, dst_point->x, dst_point->y, dst_point->x + update_w, dst_point->y + update_h);
-    if ((dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(dst_surface, &dst_rect))
+    if ((dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+            && !surface_check_block_align_rect(dst_surface, &dst_rect))
     {
         WARN("Destination rectangle not block-aligned.\n");
         return WINED3DERR_INVALIDCALL;
@@ -4316,6 +4269,174 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device,
     }
 }
 
+HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device,
+        struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
+        unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
+{
+    struct wined3d_surface *dst_surface, *src_surface;
+    struct wined3d_texture *dst_texture, *src_texture;
+    struct wined3d_resource *tmp;
+    RECT dst_rect, src_rect;
+    HRESULT hr;
+
+    TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
+            "src_resource %p, src_sub_resource_idx %u, src_box %p.\n",
+            device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z,
+            src_resource, src_sub_resource_idx, src_box);
+
+    if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx)
+    {
+        WARN("Source and destination are the same sub-resource.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (src_resource->type != dst_resource->type)
+    {
+        WARN("Resource types (%s / %s) don't match.\n",
+                debug_d3dresourcetype(dst_resource->type),
+                debug_d3dresourcetype(src_resource->type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    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 WINED3DERR_INVALIDCALL;
+    }
+
+    if (dst_resource->type != WINED3D_RTYPE_TEXTURE)
+    {
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    dst_texture = wined3d_texture_from_resource(dst_resource);
+    if (!(tmp = wined3d_texture_get_sub_resource(dst_texture, dst_sub_resource_idx)))
+    {
+        WARN("Invalid dst_sub_resource_idx %u.\n", dst_sub_resource_idx);
+        return WINED3DERR_INVALIDCALL;
+    }
+    dst_surface = surface_from_resource(tmp);
+
+    src_texture = wined3d_texture_from_resource(src_resource);
+    if (!(tmp = wined3d_texture_get_sub_resource(src_texture, src_sub_resource_idx)))
+    {
+        WARN("Invalid src_sub_resource_idx %u.\n", src_sub_resource_idx);
+        return WINED3DERR_INVALIDCALL;
+    }
+    src_surface = surface_from_resource(tmp);
+
+    dst_rect.left = dst_x;
+    dst_rect.top = dst_y;
+    dst_rect.right = dst_x + (src_box->right - src_box->left);
+    dst_rect.bottom = dst_y + (src_box->bottom - src_box->top);
+
+    src_rect.left = src_box->left;
+    src_rect.top = src_box->top;
+    src_rect.right = src_box->right;
+    src_rect.bottom = src_box->bottom;
+
+    if (FAILED(hr = wined3d_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
+        ERR("Failed to blit, hr %#x.\n", hr);
+
+    return hr;
+}
+
+void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
+        unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
+        unsigned int depth_pitch)
+{
+    struct wined3d_resource *sub_resource;
+#if defined(STAGING_CSMT)
+    struct wined3d_texture *texture;
+#else  /* STAGING_CSMT */
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_const_bo_address addr;
+    struct wined3d_context *context;
+    struct wined3d_texture *texture;
+    struct wined3d_surface *surface;
+    POINT dst_point;
+    RECT src_rect;
+#endif /* STAGING_CSMT */
+
+    TRACE("device %p, resource %p, sub_resource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u.\n",
+            device, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
+
+    if (resource->type != WINED3D_RTYPE_TEXTURE)
+    {
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
+        return;
+    }
+
+    texture = wined3d_texture_from_resource(resource);
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+    {
+        WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+        return;
+    }
+#if defined(STAGING_CSMT)
+
+#else  /* STAGING_CSMT */
+    surface = surface_from_resource(sub_resource);
+
+    src_rect.left = 0;
+    src_rect.top = 0;
+#endif /* STAGING_CSMT */
+    if (box)
+    {
+        if (box->left >= box->right || box->right > sub_resource->width
+                || box->top >= box->bottom || box->bottom > sub_resource->height)
+        {
+            WARN("Invalid box (%u, %u, %u)->(%u, %u, %u) specified.\n",
+                    box->left, box->top, box->front, box->right, box->bottom, box->back);
+            return;
+        }
+#if defined(STAGING_CSMT)
+    }
+
+    wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
+#else  /* STAGING_CSMT */
+
+        src_rect.right = box->right - box->left;
+        src_rect.bottom = box->bottom - box->top;
+        dst_point.x = box->left;
+        dst_point.y = box->top;
+    }
+    else
+    {
+        src_rect.right = sub_resource->width;
+        src_rect.bottom = sub_resource->height;
+        dst_point.x = 0;
+        dst_point.y = 0;
+    }
+
+    addr.buffer_object = 0;
+    addr.addr = data;
+
+    context = context_acquire(resource->device, NULL);
+    gl_info = context->gl_info;
+
+    /* Only load the surface for partial updates. */
+    if (!dst_point.x && !dst_point.y && src_rect.right == sub_resource->width
+            && src_rect.bottom == sub_resource->height)
+        wined3d_texture_prepare_texture(texture, context, FALSE);
+    else
+        surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
+
+    wined3d_surface_upload_data(surface, gl_info, resource->format,
+            &src_rect, row_pitch, &dst_point, FALSE, &addr);
+
+    context_release(context);
+
+    surface_validate_location(surface, WINED3D_LOCATION_TEXTURE_RGB);
+    surface_invalidate_location(surface, ~WINED3D_LOCATION_TEXTURE_RGB);
+#endif /* STAGING_CSMT */
+}
+
 HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
         struct wined3d_rendertarget_view *view, const RECT *rect, const struct wined3d_color *color)
 {
@@ -4482,13 +4603,6 @@ void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device,
     wined3d_cs_emit_set_depth_stencil_view(device->cs, view);
     if (prev)
         wined3d_rendertarget_view_decref(prev);
-}
-
-HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device,
-        UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
-{
-    TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
-            device, x_hotspot, y_hotspot, cursor_image);
 #else  /* STAGING_CSMT */
     struct wined3d_rendertarget_view *prev;
 
@@ -4548,106 +4662,115 @@ static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined
     }
 
     return texture;
+#endif /* STAGING_CSMT */
 }
 
 HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device,
-        UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
+        UINT x_hotspot, UINT y_hotspot, struct wined3d_texture *texture, unsigned int sub_resource_idx)
 {
-    TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
-            device, x_hotspot, y_hotspot, cursor_image);
+    struct wined3d_display_mode mode;
+    struct wined3d_map_desc map_desc;
+    struct wined3d_resource *sub_resource;
+    struct wined3d_surface *cursor_image;
+    HRESULT hr;
+
+    TRACE("device %p, x_hotspot %u, y_hotspot %u, texture %p, sub_resource_idx %u.\n",
+            device, x_hotspot, y_hotspot, texture, sub_resource_idx);
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx))
+            || sub_resource->type != WINED3D_RTYPE_SURFACE)
+        return WINED3DERR_INVALIDCALL;
+
+    cursor_image = surface_from_resource(sub_resource);
 
+#if !defined(STAGING_CSMT)
     if (device->cursor_texture)
     {
         wined3d_texture_decref(device->cursor_texture);
         device->cursor_texture = NULL;
     }
-#endif /* STAGING_CSMT */
 
-    if (cursor_image)
+#endif /* STAGING_CSMT */
+    if (cursor_image->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM)
     {
-        struct wined3d_display_mode mode;
-        struct wined3d_map_desc map_desc;
-        HRESULT hr;
-
-        /* MSDN: Cursor must be A8R8G8B8 */
-        if (cursor_image->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM)
-        {
-            WARN("surface %p has an invalid format.\n", cursor_image);
-            return WINED3DERR_INVALIDCALL;
-        }
+        WARN("Surface %p has an invalid format %s.\n",
+                cursor_image, debug_d3dformat(cursor_image->resource.format->id));
+        return WINED3DERR_INVALIDCALL;
+    }
 
-        if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL)))
-        {
-            ERR("Failed to get display mode, hr %#x.\n", hr);
-            return WINED3DERR_INVALIDCALL;
-        }
+    if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL)))
+    {
+        ERR("Failed to get display mode, hr %#x.\n", hr);
+        return WINED3DERR_INVALIDCALL;
+    }
 
-        /* MSDN: Cursor must be smaller than the display mode */
-        if (cursor_image->resource.width > mode.width || cursor_image->resource.height > mode.height)
-        {
-            WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
-                    cursor_image, cursor_image->resource.width, cursor_image->resource.height,
-                    mode.width, mode.height);
-            return WINED3DERR_INVALIDCALL;
-        }
+    if (cursor_image->resource.width > mode.width || cursor_image->resource.height > mode.height)
+    {
+        WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
+                cursor_image, cursor_image->resource.width, cursor_image->resource.height,
+                mode.width, mode.height);
+        return WINED3DERR_INVALIDCALL;
+    }
 
-        /* TODO: MSDN: Cursor sizes must be a power of 2 */
+    /* TODO: MSDN: Cursor sizes must be a power of 2 */
 
-        /* Do not store the surface's pointer because the application may
-         * release it after setting the cursor image. Windows doesn't
-         * addref the set surface, so we can't do this either without
-         * creating circular refcount dependencies. */
-#if defined(STAGING_CSMT)
-        device->cursorWidth = cursor_image->resource.width;
-        device->cursorHeight = cursor_image->resource.height;
-#else  /* STAGING_CSMT */
-        if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image)))
-        {
-            ERR("Failed to create cursor texture.\n");
-            return WINED3DERR_INVALIDCALL;
-        }
+    /* Do not store the surface's pointer because the application may
+     * release it after setting the cursor image. Windows doesn't
+     * addref the set surface, so we can't do this either without
+     * creating circular refcount dependencies. */
+#if !defined(STAGING_CSMT)
+    if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image)))
+    {
+        ERR("Failed to create cursor texture.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
 #endif /* STAGING_CSMT */
 
-        device->cursorWidth = cursor_image->resource.width;
-        device->cursorHeight = cursor_image->resource.height;
+    if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
+    {
+        UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8;
+        ICONINFO cursor_info;
+        DWORD *mask_bits;
+        HCURSOR cursor;
 
-        if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
-        {
-            UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8;
-            ICONINFO cursorInfo;
-            DWORD *maskBits;
-            HCURSOR cursor;
-
-            /* 32-bit user32 cursors ignore the alpha channel if it's all
-             * zeroes, and use the mask instead. Fill the mask with all ones
-             * to ensure we still get a fully transparent cursor. */
-            maskBits = HeapAlloc(GetProcessHeap(), 0, mask_size);
-            memset(maskBits, 0xff, mask_size);
-            wined3d_surface_map(cursor_image, &map_desc, NULL,
-                    WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY);
-            TRACE("width: %u height: %u.\n", cursor_image->resource.width, cursor_image->resource.height);
-
-            cursorInfo.fIcon = FALSE;
-            cursorInfo.xHotspot = x_hotspot;
-            cursorInfo.yHotspot = y_hotspot;
-            cursorInfo.hbmMask = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height,
-                    1, 1, maskBits);
-            cursorInfo.hbmColor = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height,
-                    1, 32, map_desc.data);
-            wined3d_surface_unmap(cursor_image);
-            /* Create our cursor and clean up. */
-            cursor = CreateIconIndirect(&cursorInfo);
-            if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
-            if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
-            if (device->hardwareCursor) DestroyCursor(device->hardwareCursor);
-            device->hardwareCursor = cursor;
-            if (device->bCursorVisible) SetCursor( cursor );
-            HeapFree(GetProcessHeap(), 0, maskBits);
-        }
+        /* 32-bit user32 cursors ignore the alpha channel if it's all
+         * zeroes, and use the mask instead. Fill the mask with all ones
+         * to ensure we still get a fully transparent cursor. */
+        if (!(mask_bits = HeapAlloc(GetProcessHeap(), 0, mask_size)))
+            return E_OUTOFMEMORY;
+        memset(mask_bits, 0xff, mask_size);
+
+        wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY);
+        cursor_info.fIcon = FALSE;
+        cursor_info.xHotspot = x_hotspot;
+        cursor_info.yHotspot = y_hotspot;
+        cursor_info.hbmMask = CreateBitmap(cursor_image->resource.width,
+                cursor_image->resource.height, 1, 1, mask_bits);
+        cursor_info.hbmColor = CreateBitmap(cursor_image->resource.width,
+                cursor_image->resource.height, 1, 32, map_desc.data);
+        wined3d_surface_unmap(cursor_image);
+
+        /* Create our cursor and clean up. */
+        cursor = CreateIconIndirect(&cursor_info);
+        if (cursor_info.hbmMask)
+            DeleteObject(cursor_info.hbmMask);
+        if (cursor_info.hbmColor)
+            DeleteObject(cursor_info.hbmColor);
+        if (device->hardwareCursor)
+            DestroyCursor(device->hardwareCursor);
+        device->hardwareCursor = cursor;
+        if (device->bCursorVisible)
+            SetCursor(cursor);
+
+        HeapFree(GetProcessHeap(), 0, mask_bits);
     }
 
+    TRACE("New cursor dimensions are %ux%u.\n", cursor_image->resource.width, cursor_image->resource.height);
+    device->cursorWidth = cursor_image->resource.width;
+    device->cursorHeight = cursor_image->resource.height;
     device->xHotSpot = x_hotspot;
     device->yHotSpot = y_hotspot;
+
     return WINED3D_OK;
 }
 
@@ -4752,8 +4875,6 @@ void device_delete_opengl_contexts_cs(struct wined3d_device *device, struct wine
 
     context = context_acquire(device, NULL);
     gl_info = context->gl_info;
-
-    wine_rb_clear(&device->samplers, device_free_sampler, NULL);
 #else  /* STAGING_CSMT */
             resource->resource_ops->resource_unload(resource);
         }
@@ -4896,23 +5017,21 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode,
         wined3d_device_reset_cb callback, BOOL reset_state)
 {
-    enum wined3d_format_id backbuffer_format = swapchain_desc->backbuffer_format;
     struct wined3d_resource *resource, *cursor;
     struct wined3d_swapchain *swapchain;
     struct wined3d_display_mode m;
     BOOL DisplayModeChanged;
-    BOOL update_desc = FALSE;
-    UINT backbuffer_width = swapchain_desc->backbuffer_width;
-    UINT backbuffer_height = swapchain_desc->backbuffer_height;
     HRESULT hr = WINED3D_OK;
     unsigned int i;
 
-    TRACE("device %p, swapchain_desc %p, mode %p, callback %p.\n", device, swapchain_desc, mode, callback);
+    TRACE("device %p, swapchain_desc %p, mode %p, callback %p, reset_state %#x.\n",
+            device, swapchain_desc, mode, callback, reset_state);
+
 #if defined(STAGING_CSMT)
     wined3d_cs_emit_glfinish(device->cs);
     device->cs->ops->finish(device->cs);
-#endif /* STAGING_CSMT */
 
+#endif /* STAGING_CSMT */
     if (!(swapchain = wined3d_device_get_swapchain(device, 0)))
     {
         ERR("Failed to get the first implicit swapchain.\n");
@@ -4958,12 +5077,12 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
 
     if (device->cs->onscreen_depth_stencil)
     {
-        wined3d_surface_decref(device->cs->onscreen_depth_stencil);
+        wined3d_texture_decref(device->cs->onscreen_depth_stencil->container);
         device->cs->onscreen_depth_stencil = NULL;
 #else  /* STAGING_CSMT */
     if (device->onscreen_depth_stencil)
     {
-        wined3d_surface_decref(device->onscreen_depth_stencil);
+        wined3d_texture_decref(device->onscreen_depth_stencil->container);
         device->onscreen_depth_stencil = NULL;
 #endif /* STAGING_CSMT */
     }
@@ -5001,13 +5120,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     device->cs->ops->finish(device->cs);
 
 #endif /* STAGING_CSMT */
-    /* Is it necessary to recreate the gl context? Actually every setting can be changed
-     * on an existing gl context, so there's no real need for recreation.
-     *
-     * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
-     *
-     * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
-     */
     TRACE("New params:\n");
     TRACE("backbuffer_width %u\n", swapchain_desc->backbuffer_width);
     TRACE("backbuffer_height %u\n", swapchain_desc->backbuffer_height);
@@ -5035,11 +5147,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     swapchain->desc.swap_interval = swapchain_desc->swap_interval;
     swapchain->desc.auto_restore_display_mode = swapchain_desc->auto_restore_display_mode;
 
-    /* What to do about these? */
-    if (swapchain_desc->backbuffer_count
-            && swapchain_desc->backbuffer_count != swapchain->desc.backbuffer_count)
-        FIXME("Cannot change the back buffer count yet.\n");
-
     if (swapchain_desc->device_window
             && swapchain_desc->device_window != swapchain->desc.device_window)
     {
@@ -5066,139 +5173,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         m.refresh_rate = swapchain_desc->refresh_rate;
         m.format_id = swapchain_desc->backbuffer_format;
         m.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
-    }
-
-    if (!backbuffer_width || !backbuffer_height)
-    {
-        /* The application is requesting that either the swapchain width or
-         * height be set to the corresponding dimension in the window's
-         * client rect. */
-
-        RECT client_rect;
 
-        if (!swapchain_desc->windowed)
-            return WINED3DERR_INVALIDCALL;
-
-        if (!GetClientRect(swapchain->device_window, &client_rect))
-        {
-            ERR("Failed to get client rect, last error %#x.\n", GetLastError());
-            return WINED3DERR_INVALIDCALL;
-        }
-
-        if (!backbuffer_width)
-            backbuffer_width = client_rect.right;
-
-        if (!backbuffer_height)
-            backbuffer_height = client_rect.bottom;
-    }
-
-    if (backbuffer_width != swapchain->desc.backbuffer_width
-            || backbuffer_height != swapchain->desc.backbuffer_height)
-    {
-        if (!swapchain_desc->windowed)
+        if ((m.width != swapchain->desc.backbuffer_width
+                || m.height != swapchain->desc.backbuffer_height))
             DisplayModeChanged = TRUE;
-
-        swapchain->desc.backbuffer_width = backbuffer_width;
-        swapchain->desc.backbuffer_height = backbuffer_height;
-        update_desc = TRUE;
-    }
-
-    if (backbuffer_format == WINED3DFMT_UNKNOWN)
-    {
-        if (!swapchain_desc->windowed)
-            return WINED3DERR_INVALIDCALL;
-        backbuffer_format = swapchain->original_mode.format_id;
-    }
-
-    if (backbuffer_format != swapchain->desc.backbuffer_format)
-    {
-        swapchain->desc.backbuffer_format = backbuffer_format;
-        update_desc = TRUE;
-    }
-
-    if (swapchain_desc->multisample_type != swapchain->desc.multisample_type
-            || swapchain_desc->multisample_quality != swapchain->desc.multisample_quality)
-    {
-        swapchain->desc.multisample_type = swapchain_desc->multisample_type;
-        swapchain->desc.multisample_quality = swapchain_desc->multisample_quality;
-        update_desc = TRUE;
-    }
-
-    if (update_desc)
-    {
-        UINT i;
-
-        if (FAILED(hr = wined3d_texture_update_desc(swapchain->front_buffer, 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_texture_update_desc(swapchain->back_buffers[i], 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 !defined(STAGING_CSMT)
-    if (device->auto_depth_stencil_view)
-    {
-        wined3d_rendertarget_view_decref(device->auto_depth_stencil_view);
-        device->auto_depth_stencil_view = NULL;
-    }
-#endif /* STAGING_CSMT */
-    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)))
-        {
-            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 !defined(STAGING_CSMT)
-    if (device->back_buffer_view)
-    {
-        wined3d_rendertarget_view_decref(device->back_buffer_view);
-        device->back_buffer_view = NULL;
-    }
-#endif /* STAGING_CSMT */
-    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
@@ -5263,6 +5241,75 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         device->exStyle = exStyle;
     }
 
+    if (FAILED(hr = wined3d_swapchain_resize_buffers(swapchain, swapchain_desc->backbuffer_count,
+            swapchain_desc->backbuffer_width, swapchain_desc->backbuffer_height, swapchain_desc->backbuffer_format,
+            swapchain_desc->multisample_type, swapchain_desc->multisample_quality)))
+        return hr;
+
+#if !defined(STAGING_CSMT)
+    if (device->auto_depth_stencil_view)
+    {
+        wined3d_rendertarget_view_decref(device->auto_depth_stencil_view);
+        device->auto_depth_stencil_view = NULL;
+    }
+#endif /* STAGING_CSMT */
+    if (swapchain->desc.enable_auto_depth_stencil)
+    {
+        struct wined3d_resource_desc texture_desc;
+        struct wined3d_texture *texture;
+        struct wined3d_rendertarget_view_desc view_desc;
+
+        TRACE("Creating the depth stencil buffer\n");
+
+        texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+        texture_desc.format = swapchain->desc.auto_depth_stencil_format;
+        texture_desc.multisample_type = swapchain->desc.multisample_type;
+        texture_desc.multisample_quality = swapchain->desc.multisample_quality;
+        texture_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+        texture_desc.pool = WINED3D_POOL_DEFAULT;
+        texture_desc.width = swapchain->desc.backbuffer_width;
+        texture_desc.height = swapchain->desc.backbuffer_height;
+        texture_desc.depth = 1;
+        texture_desc.size = 0;
+
+        if (FAILED(hr = device->device_parent->ops->create_swapchain_texture(device->device_parent,
+                device->device_parent, &texture_desc, &texture)))
+        {
+            ERR("Failed to create the auto depth/stencil surface, hr %#x.\n", hr);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        view_desc.format_id = texture->resource.format->id;
+        view_desc.u.texture.level_idx = 0;
+        view_desc.u.texture.layer_idx = 0;
+        view_desc.u.texture.layer_count = 1;
+        hr = wined3d_rendertarget_view_create(&view_desc, &texture->resource,
+                NULL, &wined3d_null_parent_ops, &device->auto_depth_stencil_view);
+        wined3d_texture_decref(texture);
+        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 !defined(STAGING_CSMT)
+    if (device->back_buffer_view)
+    {
+        wined3d_rendertarget_view_decref(device->back_buffer_view);
+        device->back_buffer_view = NULL;
+    }
+#endif /* STAGING_CSMT */
+    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;
+    }
+
     wine_rb_clear(&device->samplers, device_free_sampler, NULL);
 
     if (reset_state)
@@ -5335,9 +5382,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
     }
 
-    swapchain_update_render_to_fbo(swapchain);
-    swapchain_update_draw_bindings(swapchain);
-
     if (reset_state && device->d3d_initialized)
         hr = create_primary_opengl_context(device, swapchain);
 
@@ -5661,7 +5705,7 @@ void device_invalidate_state(const struct wined3d_device *device, DWORD state)
         context->dirtyArray[context->numDirtyEntries++] = rep;
         idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
         shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
-        context->isStateDirty[idx] |= (1 << shift);
+        context->isStateDirty[idx] |= (1u << shift);
     }
 }
 
@@ -5737,7 +5781,7 @@ struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT
     gl_info = context->gl_info;
 
     GL_EXTCALL(glGenBuffers(1, &ret->name));
-    if (type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+    if (type_hint == GL_ELEMENT_ARRAY_BUFFER)
         context_invalidate_state(context, STATE_INDEXBUFFER);
     GL_EXTCALL(glBindBuffer(type_hint, ret->name));
     GL_EXTCALL(glBufferData(type_hint, size, NULL, gl_usage));
index 5a78b1b..62bfd32 100644 (file)
@@ -113,6 +113,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_draw_buffers",                 ARB_DRAW_BUFFERS              },
     {"GL_ARB_draw_elements_base_vertex",    ARB_DRAW_ELEMENTS_BASE_VERTEX },
     {"GL_ARB_draw_instanced",               ARB_DRAW_INSTANCED            },
+    {"GL_ARB_ES2_compatibility",            ARB_ES2_COMPATIBILITY         },
     {"GL_ARB_fragment_program",             ARB_FRAGMENT_PROGRAM          },
     {"GL_ARB_fragment_shader",              ARB_FRAGMENT_SHADER           },
     {"GL_ARB_framebuffer_object",           ARB_FRAMEBUFFER_OBJECT        },
@@ -249,19 +250,21 @@ const GLenum magLookup[] =
     GL_NEAREST, GL_NEAREST, GL_LINEAR,
 };
 
-struct wined3d_caps_gl_ctx
-{
-    HDC dc;
-    HWND wnd;
-    HGLRC gl_ctx;
-    HDC restore_dc;
-    HGLRC restore_gl_ctx;
-};
-
 static void wined3d_caps_gl_ctx_destroy(const struct wined3d_caps_gl_ctx *ctx)
 {
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+
     TRACE("Destroying caps GL context.\n");
 
+    /* Both glDeleteProgram and glDeleteBuffers silently ignore 0 IDs but
+     * this function might be called before the relevant function pointers
+     * in gl_info are initialized. */
+    if (ctx->test_program_id || ctx->test_vbo)
+    {
+        GL_EXTCALL(glDeleteProgram(ctx->test_program_id));
+        GL_EXTCALL(glDeleteBuffers(1, &ctx->test_vbo));
+    }
+
     if (!wglMakeCurrent(NULL, NULL))
         ERR("Failed to disable caps GL context.\n");
 
@@ -308,7 +311,7 @@ static BOOL wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_
     return TRUE;
 }
 
-static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx)
+static BOOL wined3d_caps_gl_ctx_create(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx)
 {
     PIXELFORMATDESCRIPTOR pfd;
     int iPixelFormat;
@@ -366,6 +369,7 @@ static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx)
         goto fail;
     }
 
+    ctx->gl_info = &adapter->gl_info;
     return TRUE;
 
 fail:
@@ -1233,6 +1237,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS350M,    "NVIDIA GeForce GTS 350M",          DRIVER_NVIDIA_GEFORCE8,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_410M,       "NVIDIA GeForce 410M",              DRIVER_NVIDIA_GEFORCE8,  512},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT420,      "NVIDIA GeForce GT 420",            DRIVER_NVIDIA_GEFORCE8,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT425M,     "NVIDIA GeForce GT 425M",           DRIVER_NVIDIA_GEFORCE8,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT430,      "NVIDIA GeForce GT 430",            DRIVER_NVIDIA_GEFORCE8,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT440,      "NVIDIA GeForce GT 440",            DRIVER_NVIDIA_GEFORCE8,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS450,     "NVIDIA GeForce GTS 450",           DRIVER_NVIDIA_GEFORCE8,  1024},
@@ -1286,6 +1291,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3200,         "ATI Radeon HD 3200 Graphics",      DRIVER_AMD_R600,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3850,         "ATI Radeon HD 3850 AGP",           DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4200M,        "ATI Mobility Radeon HD 4200",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4350,         "ATI Radeon HD 4350",               DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        DRIVER_AMD_R600,         512 },
@@ -1776,6 +1782,7 @@ cards_nvidia_binary[] =
     {"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 425M",                     CARD_NVIDIA_GEFORCE_GT425M},    /* Geforce 400 - lowend mobile */
     {"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 */
@@ -2049,7 +2056,7 @@ cards_amd_mesa[] =
     /* R600 */
     {"R680",                        CARD_AMD_RADEON_HD2900},
     {"R600",                        CARD_AMD_RADEON_HD2900},
-    {"RV670",                       CARD_AMD_RADEON_HD2900},
+    {"RV670",                       CARD_AMD_RADEON_HD3850},
     {"RV635",                       CARD_AMD_RADEON_HD2600},
     {"RV630",                       CARD_AMD_RADEON_HD2600},
     {"RV620",                       CARD_AMD_RADEON_HD2350},
@@ -2514,6 +2521,12 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     /* GL_ARB_draw_instanced */
     USE_GL_FUNC(glDrawArraysInstancedARB)
     USE_GL_FUNC(glDrawElementsInstancedARB)
+    /* GL_ARB_ES2_compatibility */
+    USE_GL_FUNC(glReleaseShaderCompiler)
+    USE_GL_FUNC(glShaderBinary)
+    USE_GL_FUNC(glGetShaderPrecisionFormat)
+    USE_GL_FUNC(glDepthRangef)
+    USE_GL_FUNC(glClearDepthf)
     /* GL_ARB_framebuffer_object */
     USE_GL_FUNC(glBindFramebuffer)
     USE_GL_FUNC(glBindRenderbuffer)
@@ -2932,6 +2945,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glBeginQuery)               /* OpenGL 1.5 */
     USE_GL_FUNC(glBindAttribLocation)       /* OpenGL 2.0 */
     USE_GL_FUNC(glBindBuffer)               /* OpenGL 1.5 */
+    USE_GL_FUNC(glBindVertexArray)          /* OpenGL 3.0 */
     USE_GL_FUNC(glBlendColor)               /* OpenGL 1.4 */
     USE_GL_FUNC(glBlendEquation)            /* OpenGL 1.4 */
     USE_GL_FUNC(glBlendEquationSeparate)    /* OpenGL 2.0 */
@@ -2946,10 +2960,14 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glCompressedTexSubImage3D)  /* OpenGL 1.3 */
     USE_GL_FUNC(glCreateProgram)            /* OpenGL 2.0 */
     USE_GL_FUNC(glCreateShader)             /* OpenGL 2.0 */
+    USE_GL_FUNC(glDebugMessageCallback)     /* OpenGL 4.3 */
+    USE_GL_FUNC(glDebugMessageControl)      /* OpenGL 4.3 */
+    USE_GL_FUNC(glDebugMessageInsert)       /* OpenGL 4.3 */
     USE_GL_FUNC(glDeleteBuffers)            /* OpenGL 1.5 */
     USE_GL_FUNC(glDeleteProgram)            /* OpenGL 2.0 */
     USE_GL_FUNC(glDeleteQueries)            /* OpenGL 1.5 */
     USE_GL_FUNC(glDeleteShader)             /* OpenGL 2.0 */
+    USE_GL_FUNC(glDeleteVertexArrays)       /* OpenGL 3.0 */
     USE_GL_FUNC(glDetachShader)             /* OpenGL 2.0 */
     USE_GL_FUNC(glDisableVertexAttribArray) /* OpenGL 2.0 */
     USE_GL_FUNC(glDrawArraysInstanced)      /* OpenGL 3.1 */
@@ -2959,11 +2977,13 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glEndQuery)                 /* OpenGL 1.5 */
     USE_GL_FUNC(glGenBuffers)               /* OpenGL 1.5 */
     USE_GL_FUNC(glGenQueries)               /* OpenGL 1.5 */
+    USE_GL_FUNC(glGenVertexArrays)          /* OpenGL 3.0 */
     USE_GL_FUNC(glGetActiveUniform)         /* OpenGL 2.0 */
     USE_GL_FUNC(glGetAttachedShaders)       /* OpenGL 2.0 */
     USE_GL_FUNC(glGetAttribLocation)        /* OpenGL 2.0 */
     USE_GL_FUNC(glGetBufferSubData)         /* OpenGL 1.5 */
     USE_GL_FUNC(glGetCompressedTexImage)    /* OpenGL 1.3 */
+    USE_GL_FUNC(glGetDebugMessageLog)       /* OpenGL 4.3 */
     USE_GL_FUNC(glGetProgramInfoLog)        /* OpenGL 2.0 */
     USE_GL_FUNC(glGetProgramiv)             /* OpenGL 2.0 */
     USE_GL_FUNC(glGetQueryiv)               /* OpenGL 1.5 */
@@ -3061,12 +3081,16 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     MAP_GL_FUNCTION(glCompressedTexSubImage3D, glCompressedTexSubImage3DARB);
     MAP_GL_FUNCTION(glCreateProgram, glCreateProgramObjectARB);
     MAP_GL_FUNCTION(glCreateShader, glCreateShaderObjectARB);
+    MAP_GL_FUNCTION(glDebugMessageCallback, glDebugMessageCallbackARB);
+    MAP_GL_FUNCTION(glDebugMessageControl, glDebugMessageControlARB);
+    MAP_GL_FUNCTION(glDebugMessageInsert, glDebugMessageInsertARB);
     MAP_GL_FUNCTION(glDeleteBuffers, glDeleteBuffersARB);
     MAP_GL_FUNCTION(glDeleteProgram, glDeleteObjectARB);
     MAP_GL_FUNCTION(glDeleteQueries, glDeleteQueriesARB);
     MAP_GL_FUNCTION(glDeleteShader, glDeleteObjectARB);
     MAP_GL_FUNCTION(glDetachShader, glDetachObjectARB);
     MAP_GL_FUNCTION(glDisableVertexAttribArray, glDisableVertexAttribArrayARB);
+    MAP_GL_FUNCTION(glDrawArraysInstanced, glDrawArraysInstancedARB);
     MAP_GL_FUNCTION(glDrawBuffers, glDrawBuffersARB);
     MAP_GL_FUNCTION(glDrawElementsInstanced, glDrawElementsInstancedARB);
     MAP_GL_FUNCTION(glEnableVertexAttribArray, glEnableVertexAttribArrayARB);
@@ -3078,6 +3102,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     MAP_GL_FUNCTION(glGetAttribLocation, glGetAttribLocationARB);
     MAP_GL_FUNCTION(glGetBufferSubData, glGetBufferSubDataARB);
     MAP_GL_FUNCTION(glGetCompressedTexImage, glGetCompressedTexImageARB);
+    MAP_GL_FUNCTION(glGetDebugMessageLog, glGetDebugMessageLogARB);
     MAP_GL_FUNCTION(glGetProgramInfoLog, glGetInfoLogARB);
     MAP_GL_FUNCTION(glGetProgramiv, glGetObjectParameterivARB);
     MAP_GL_FUNCTION(glGetQueryiv, glGetQueryivARB);
@@ -3376,6 +3401,82 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
 /* Context activation is done by the caller. */
 static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
 {
+    static const struct
+    {
+        enum wined3d_gl_extension extension;
+        DWORD min_gl_version;
+    }
+    core_extensions[] =
+    {
+        {EXT_TEXTURE3D,                    MAKEDWORD_VERSION(1, 2)},
+        {ARB_MULTISAMPLE,                  MAKEDWORD_VERSION(1, 3)},
+        {ARB_MULTITEXTURE,                 MAKEDWORD_VERSION(1, 3)},
+        {ARB_TEXTURE_BORDER_CLAMP,         MAKEDWORD_VERSION(1, 3)},
+        {ARB_TEXTURE_COMPRESSION,          MAKEDWORD_VERSION(1, 3)},
+        {ARB_TEXTURE_CUBE_MAP,             MAKEDWORD_VERSION(1, 3)},
+        {ARB_DEPTH_TEXTURE,                MAKEDWORD_VERSION(1, 4)},
+        {ARB_POINT_PARAMETERS,             MAKEDWORD_VERSION(1, 4)},
+        {ARB_SHADOW,                       MAKEDWORD_VERSION(1, 4)},
+        {ARB_TEXTURE_MIRRORED_REPEAT,      MAKEDWORD_VERSION(1, 4)},
+        {EXT_BLEND_COLOR,                  MAKEDWORD_VERSION(1, 4)},
+        {EXT_BLEND_FUNC_SEPARATE,          MAKEDWORD_VERSION(1, 4)},
+        {EXT_BLEND_MINMAX,                 MAKEDWORD_VERSION(1, 4)},
+        {EXT_BLEND_SUBTRACT,               MAKEDWORD_VERSION(1, 4)},
+        {EXT_STENCIL_WRAP,                 MAKEDWORD_VERSION(1, 4)},
+        {NV_POINT_SPRITE,                  MAKEDWORD_VERSION(1, 4)},
+        {ARB_OCCLUSION_QUERY,              MAKEDWORD_VERSION(1, 5)},
+        {ARB_VERTEX_BUFFER_OBJECT,         MAKEDWORD_VERSION(1, 5)},
+        {ARB_DRAW_BUFFERS,                 MAKEDWORD_VERSION(2, 0)},
+        {ARB_FRAGMENT_SHADER,              MAKEDWORD_VERSION(2, 0)},
+        {ARB_SHADING_LANGUAGE_100,         MAKEDWORD_VERSION(2, 0)},
+        {ARB_TEXTURE_NON_POWER_OF_TWO,     MAKEDWORD_VERSION(2, 0)},
+        {ARB_VERTEX_SHADER,                MAKEDWORD_VERSION(2, 0)},
+        {EXT_BLEND_EQUATION_SEPARATE,      MAKEDWORD_VERSION(2, 0)},
+        {ARB_PIXEL_BUFFER_OBJECT,          MAKEDWORD_VERSION(2, 1)},
+        {EXT_TEXTURE_SRGB,                 MAKEDWORD_VERSION(2, 1)},
+        {ARB_COLOR_BUFFER_FLOAT,           MAKEDWORD_VERSION(3, 0)},
+        {ARB_DEPTH_BUFFER_FLOAT,           MAKEDWORD_VERSION(3, 0)},
+        {ARB_FRAMEBUFFER_OBJECT,           MAKEDWORD_VERSION(3, 0)},
+        {ARB_FRAMEBUFFER_SRGB,             MAKEDWORD_VERSION(3, 0)},
+        {ARB_HALF_FLOAT_PIXEL,             MAKEDWORD_VERSION(3, 0)},
+        {ARB_HALF_FLOAT_VERTEX,            MAKEDWORD_VERSION(3, 0)},
+        {ARB_MAP_BUFFER_RANGE,             MAKEDWORD_VERSION(3, 0)},
+        {ARB_TEXTURE_COMPRESSION_RGTC,     MAKEDWORD_VERSION(3, 0)},
+        {ARB_TEXTURE_FLOAT,                MAKEDWORD_VERSION(3, 0)},
+        {ARB_TEXTURE_RG,                   MAKEDWORD_VERSION(3, 0)},
+        {EXT_DRAW_BUFFERS2,                MAKEDWORD_VERSION(3, 0)},
+        /* We don't want to enable EXT_GPU_SHADER4: even though similar
+         * functionality is available in core GL 3.0 / GLSL 1.30, it's different
+         * enough that reusing the same flag for the new features hurts more
+         * than it helps. */
+        /* EXT_framebuffer_object, EXT_framebuffer_blit,
+         * EXT_framebuffer_multisample and EXT_packed_depth_stencil
+         * are integrated into ARB_framebuffer_object. */
+
+        {ARB_DRAW_INSTANCED,               MAKEDWORD_VERSION(3, 1)},
+        {ARB_UNIFORM_BUFFER_OBJECT,        MAKEDWORD_VERSION(3, 1)},
+        {EXT_TEXTURE_SNORM,                MAKEDWORD_VERSION(3, 1)},
+        /* We don't need or want GL_ARB_texture_rectangle (core in 3.1). */
+
+        {ARB_DRAW_ELEMENTS_BASE_VERTEX,    MAKEDWORD_VERSION(3, 2)},
+        /* ARB_geometry_shader4 exposes a somewhat different API compared to 3.2
+         * core geometry shaders so it's not really correct to expose the
+         * extension for core-only support. */
+        {ARB_PROVOKING_VERTEX,             MAKEDWORD_VERSION(3, 2)},
+        {ARB_SYNC,                         MAKEDWORD_VERSION(3, 2)},
+        {ARB_VERTEX_ARRAY_BGRA,            MAKEDWORD_VERSION(3, 2)},
+
+        {ARB_BLEND_FUNC_EXTENDED,          MAKEDWORD_VERSION(3, 3)},
+        {ARB_INSTANCED_ARRAYS,             MAKEDWORD_VERSION(3, 3)},
+        {ARB_SAMPLER_OBJECTS,              MAKEDWORD_VERSION(3, 3)},
+        {ARB_SHADER_BIT_ENCODING,          MAKEDWORD_VERSION(3, 3)},
+        {ARB_TIMER_QUERY,                  MAKEDWORD_VERSION(3, 3)},
+
+        {ARB_MAP_BUFFER_ALIGNMENT,         MAKEDWORD_VERSION(4, 2)},
+
+        {ARB_DEBUG_OUTPUT,                 MAKEDWORD_VERSION(4, 3)},
+        {ARB_INTERNALFORMAT_QUERY2,        MAKEDWORD_VERSION(4, 3)},
+    };
     struct wined3d_driver_info *driver_info = &adapter->driver_info;
     const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
@@ -3386,9 +3487,9 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     const char *WGL_Extensions = NULL;
     enum wined3d_gl_vendor gl_vendor;
     enum wined3d_pci_device device;
-    DWORD gl_version;
+    DWORD gl_version, gl_ext_emul_mask;
     HDC hdc;
-    unsigned int i;
+    unsigned int i, j;
     GLint context_profile = 0;
 
     TRACE("adapter %p.\n", adapter);
@@ -3463,30 +3564,25 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
         parse_extension_string(gl_info, WGL_Extensions, wgl_extension_map,
                 sizeof(wgl_extension_map) / sizeof(*wgl_extension_map));
 
-    if (!gl_info->supported[EXT_TEXTURE3D] && gl_version >= MAKEDWORD_VERSION(1, 2))
-    {
-        TRACE("GL CORE: GL_EXT_texture3D support.\n");
-        gl_info->supported[EXT_TEXTURE3D] = TRUE;
-    }
-
-    if (!gl_info->supported[NV_POINT_SPRITE] && gl_version >= MAKEDWORD_VERSION(1, 4))
-    {
-        TRACE("GL CORE: GL_NV_point_sprite support.\n");
-        gl_info->supported[NV_POINT_SPRITE] = TRUE;
-    }
-
-    if ((!gl_info->supported[EXT_BLEND_MINMAX] || !gl_info->supported[EXT_BLEND_SUBTRACT])
-            && gl_version >= MAKEDWORD_VERSION(1, 4))
+    for (i = 0; i < ARRAY_SIZE(core_extensions); ++i)
     {
-        TRACE("GL CORE: GL_EXT_blend_minmax / GL_EXT_blend_subtract support.\n");
-        gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
-        gl_info->supported[EXT_BLEND_SUBTRACT] = TRUE;
-    }
+        if (!gl_info->supported[core_extensions[i].extension]
+                && gl_version >= core_extensions[i].min_gl_version)
+        {
+            for (j = 0; j < ARRAY_SIZE(gl_extension_map); ++j)
+                if (gl_extension_map[j].extension == core_extensions[i].extension)
+                    break;
 
-    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_version >= MAKEDWORD_VERSION(2, 0))
-    {
-        TRACE("GL CORE: GL_ARB_texture_non_power_of_two support.\n");
-        gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
+            if (j < ARRAY_SIZE(gl_extension_map))
+            {
+                TRACE("GL CORE: %s support.\n", gl_extension_map[j].extension_string);
+                gl_info->supported[core_extensions[i].extension] = TRUE;
+            }
+            else
+            {
+                FIXME("GL extension %u not in the GL extensions map.\n", core_extensions[i].extension);
+            }
+        }
     }
 
     if (gl_info->supported[EXT_BLEND_MINMAX] || gl_info->supported[EXT_BLEND_SUBTRACT])
@@ -3494,6 +3590,8 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
 
     if (gl_version >= MAKEDWORD_VERSION(2, 0))
         gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE;
+    if (gl_version >= MAKEDWORD_VERSION(3, 2))
+        gl_info->supported[WINED3D_GL_VERSION_3_2] = TRUE;
 
     if (gl_info->supported[APPLE_FENCE])
     {
@@ -3657,11 +3755,13 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     adapter->d3d_info.limits.ps_version = shader_caps.ps_version;
     adapter->d3d_info.limits.vs_uniform_count = shader_caps.vs_uniform_count;
     adapter->d3d_info.limits.ps_uniform_count = shader_caps.ps_uniform_count;
+    adapter->d3d_info.limits.varying_count = shader_caps.varying_count;
 
     adapter->vertex_pipe->vp_get_caps(gl_info, &vertex_caps);
     adapter->d3d_info.xyzrhw = vertex_caps.xyzrhw;
     adapter->d3d_info.ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
     adapter->d3d_info.limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
+    adapter->d3d_info.emulated_flatshading = vertex_caps.emulated_flatshading;
 
     adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
     adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
@@ -3749,11 +3849,25 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
 
     adapter->d3d_info.valid_rt_mask = 0;
     for (i = 0; i < gl_info->limits.buffers; ++i)
-        adapter->d3d_info.valid_rt_mask |= (1 << i);
+        adapter->d3d_info.valid_rt_mask |= (1u << i);
+
+    if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    {
+        GLuint vao;
+
+        GL_EXTCALL(glGenVertexArrays(1, &vao));
+        GL_EXTCALL(glBindVertexArray(vao));
+        checkGLcall("creating VAO");
+    }
 
     fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
     init_driver_info(gl_info, driver_info, card_vendor, device);
-    add_gl_compat_wrappers(gl_info);
+    gl_ext_emul_mask = adapter->vertex_pipe->vp_get_emul_mask(gl_info)
+            | adapter->fragment_pipe->get_emul_mask(gl_info);
+    if (gl_ext_emul_mask & GL_EXT_EMUL_ARB_MULTITEXTURE)
+        install_gl_compat_wrapper(gl_info, ARB_MULTITEXTURE);
+    if (gl_ext_emul_mask & GL_EXT_EMUL_EXT_FOG_COORD)
+        install_gl_compat_wrapper(gl_info, EXT_FOG_COORD);
 
     return TRUE;
 }
@@ -4194,50 +4308,28 @@ HRESULT CDECL wined3d_get_adapter_raster_status(const struct wined3d *wined3d, U
 static BOOL wined3d_check_pixel_format_color(const struct wined3d_gl_info *gl_info,
         const struct wined3d_pixel_format *cfg, const struct wined3d_format *format)
 {
-    BYTE redSize, greenSize, blueSize, alphaSize, colorBits;
-
     /* Float formats need FBOs. If FBOs are used this function isn't called */
     if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT)
         return FALSE;
 
-    if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
-        if (!getColorBits(format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
-        {
-            ERR("Unable to check compatibility for format %s.\n", debug_d3dformat(format->id));
-            return FALSE;
-        }
-
-        if(cfg->redSize < redSize)
-            return FALSE;
-
-        if(cfg->greenSize < greenSize)
-            return FALSE;
-
-        if(cfg->blueSize < blueSize)
-            return FALSE;
-
-        if(cfg->alphaSize < alphaSize)
-            return FALSE;
+    /* Probably a RGBA_float or color index mode. */
+    if (cfg->iPixelType != WGL_TYPE_RGBA_ARB)
+        return FALSE;
 
-        return TRUE;
-    }
+    if (cfg->redSize < format->red_size
+            || cfg->greenSize < format->green_size
+            || cfg->blueSize < format->blue_size
+            || cfg->alphaSize < format->alpha_size)
+        return FALSE;
 
-    /* Probably a RGBA_float or color index mode */
-    return FALSE;
+    return TRUE;
 }
 
 static BOOL wined3d_check_pixel_format_depth(const struct wined3d_gl_info *gl_info,
         const struct wined3d_pixel_format *cfg, const struct wined3d_format *format)
 {
-    BYTE depthSize, stencilSize;
     BOOL lockable = FALSE;
 
-    if (!getDepthStencilBits(format, &depthSize, &stencilSize))
-    {
-        ERR("Unable to check compatibility for format %s.\n", debug_d3dformat(format->id));
-        return FALSE;
-    }
-
     /* Float formats need FBOs. If FBOs are used this function isn't called */
     if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT)
         return FALSE;
@@ -4245,15 +4337,19 @@ static BOOL wined3d_check_pixel_format_depth(const struct wined3d_gl_info *gl_in
     if ((format->id == WINED3DFMT_D16_LOCKABLE) || (format->id == WINED3DFMT_D32_FLOAT))
         lockable = TRUE;
 
-    /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
-     * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
-     * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
-    if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
+    /* On some modern cards like the Geforce8/9, GLX doesn't offer some
+     * dephth/stencil formats which D3D9 reports. We can safely report
+     * "compatible" formats (e.g. D24 can be used for D16) as long as we
+     * aren't dealing with a lockable format. This also helps D3D <= 7 as they
+     * expect D16 which isn't offered without this on Geforce8 cards. */
+    if (!(cfg->depthSize == format->depth_size || (!lockable && cfg->depthSize > format->depth_size)))
         return FALSE;
 
-    /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
-     * allow more stencil bits than requested. */
-    if(cfg->stencilSize < stencilSize)
+    /* Some cards like Intel i915 ones only offer D24S8 but lots of games also
+     * need a format without stencil. We can allow a mismatch if the format
+     * doesn't have any stencil bits. If it does have stencil bits the size
+     * must match, or stencil wrapping would break. */
+    if (format->stencil_size && cfg->stencilSize != format->stencil_size)
         return FALSE;
 
     return TRUE;
@@ -4346,10 +4442,7 @@ HRESULT CDECL wined3d_check_device_multisample_type(const struct wined3d *wined3
             TRACE("Overriding MSAA quality levels to %i\n", *quality_levels);
         }
         else if (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
-        {
             *quality_levels = gl_info->limits.samples;
-            WARN("probably wrong, setting quality_levels to %d\n", *quality_levels);
-        }
         else
             *quality_levels = 1;
     }
@@ -4410,17 +4503,15 @@ static BOOL CheckRenderTargetCapability(const struct wined3d_adapter *adapter,
         return FALSE;
     if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
     {
-        BYTE AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
-        BYTE CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
         const struct wined3d_pixel_format *cfgs = adapter->cfgs;
         unsigned int i;
 
-        getColorBits(adapter_format, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
-        getColorBits(check_format, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
-
-        /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
-         * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
-        if (!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue)))
+        /* In backbuffer mode the front and backbuffer share the same WGL
+         * pixelformat. The format must match in RGB, alpha is allowed to be
+         * different. (Only the backbuffer can have alpha.) */
+        if (adapter_format->red_size != check_format->red_size
+                || adapter_format->green_size != check_format->green_size
+                || adapter_format->blue_size != check_format->blue_size)
         {
             TRACE("[FAILED]\n");
             return FALSE;
@@ -5395,8 +5486,8 @@ HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, e
     struct wined3d_device *object;
     HRESULT hr;
 
-    TRACE("wined3d %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x, device_parent %p, device %p.\n",
-            wined3d, adapter_idx, device_type, focus_window, flags, device_parent, device);
+    TRACE("wined3d %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x, surface_alignment %u, device_parent %p, device %p.\n",
+            wined3d, adapter_idx, device_type, focus_window, flags, surface_alignment, device_parent, device);
 
     /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
      * number and create a device without a 3D adapter for 2D only operation. */
@@ -5804,7 +5895,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
     TRACE("Allocated LUID %08x:%08x for adapter %p.\n",
             adapter->luid.HighPart, adapter->luid.LowPart, adapter);
 
-    if (!wined3d_caps_gl_ctx_create(&caps_gl_ctx))
+    if (!wined3d_caps_gl_ctx_create(adapter, &caps_gl_ctx))
     {
         ERR("Failed to get a GL context for adapter %p.\n", adapter);
         return FALSE;
@@ -5851,7 +5942,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
         return FALSE;
     }
 
-    if (!wined3d_adapter_init_format_info(adapter))
+    if (!wined3d_adapter_init_format_info(adapter, &caps_gl_ctx))
     {
         ERR("Failed to initialize GL format info.\n");
         wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
@@ -5859,6 +5950,10 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
         return FALSE;
     }
 
+    gl_info->fixed_polyoffset_scale = wined3d_adapter_find_polyoffset_scale(&caps_gl_ctx, GL_DEPTH_COMPONENT);
+    if (gl_info->supported[ARB_DEPTH_BUFFER_FLOAT])
+        gl_info->float_polyoffset_scale = wined3d_adapter_find_polyoffset_scale(&caps_gl_ctx, GL_DEPTH32F_STENCIL8);
+
     adapter->vram_bytes = adapter->driver_info.vram_bytes;
     adapter->vram_bytes_used = 0;
     TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->vram_bytes));
index 472db32..ccc0706 100644 (file)
@@ -143,13 +143,13 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
     /* Start drawing in GL */
     gl_info->gl_ops.gl.p_glBegin(glPrimType);
 
-    if (si->use_map & (1 << WINED3D_FFP_POSITION))
+    if (si->use_map & (1u << WINED3D_FFP_POSITION))
     {
         element = &si->elements[WINED3D_FFP_POSITION];
         position = element->data.addr;
     }
 
-    if (si->use_map & (1 << WINED3D_FFP_NORMAL))
+    if (si->use_map & (1u << WINED3D_FFP_NORMAL))
     {
         element = &si->elements[WINED3D_FFP_NORMAL];
         normal = element->data.addr;
@@ -160,7 +160,7 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
     }
 
     num_untracked_materials = context->num_untracked_materials;
-    if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
+    if (si->use_map & (1u << WINED3D_FFP_DIFFUSE))
     {
         element = &si->elements[WINED3D_FFP_DIFFUSE];
         diffuse = element->data.addr;
@@ -173,7 +173,7 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
         gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     }
 
-    if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
+    if (si->use_map & (1u << WINED3D_FFP_SPECULAR))
     {
         element = &si->elements[WINED3D_FFP_SPECULAR];
         specular = element->data.addr;
@@ -233,11 +233,11 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
             continue;
         }
 
-        if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))
+        if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coordIdx)))
         {
             element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
             texCoords[coordIdx] = element->data.addr;
-            tex_mask |= (1 << textureNo);
+            tex_mask |= (1u << textureNo);
         }
         else
         {
@@ -372,9 +372,9 @@ static inline void send_attribute(const struct wined3d_gl_info *gl_info,
             if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
             {
                 const DWORD *src = ptr;
-                DWORD c = *src & 0xff00ff00;
-                c |= (*src & 0xff0000) >> 16;
-                c |= (*src & 0xff) << 16;
+                DWORD c = *src & 0xff00ff00u;
+                c |= (*src & 0xff0000u) >> 16;
+                c |= (*src & 0xffu) << 16;
                 GL_EXTCALL(glVertexAttrib4Nubv(index, (GLubyte *)&c));
                 break;
             }
@@ -505,7 +505,7 @@ static void drawStridedSlowVs(struct wined3d_context *context, const struct wine
 
         for (i = MAX_ATTRIBS - 1; i >= 0; i--)
         {
-            if (!(si->use_map & (1 << i))) continue;
+            if (!(si->use_map & (1u << i))) continue;
 
             ptr = si->elements[i].data.addr + si->elements[i].stride * SkipnStrides;
 
@@ -546,7 +546,7 @@ static void drawStridedInstanced(struct wined3d_context *context, const struct w
 
     for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i)
     {
-        if (!(si->use_map & (1 << i))) continue;
+        if (!(si->use_map & (1u << i))) continue;
 
         if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
         {
@@ -594,7 +594,7 @@ static void remove_vbos(struct wined3d_context *context,
     {
         struct wined3d_stream_info_element *e;
 
-        if (!(s->use_map & (1 << i))) continue;
+        if (!(s->use_map & (1u << i))) continue;
 
         e = &s->elements[i];
         if (e->data.buffer_object)
@@ -632,6 +632,9 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
 
 #if defined(STAGING_CSMT)
     context = context_acquire(device, wined3d_rendertarget_view_get_surface(state->fb.render_targets[0]));
+#else  /* STAGING_CSMT */
+    context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]));
+#endif /* STAGING_CSMT */
     if (!context->valid)
     {
         context_release(context);
@@ -645,6 +648,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
         /* Invalidate the back buffer memory so LockRect will read it the next time */
         for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
         {
+#if defined(STAGING_CSMT)
             struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(state->fb.render_targets[i]);
             if (target)
             {
@@ -673,29 +677,15 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
 
             if (ds->resource.locations & location)
 #else  /* STAGING_CSMT */
-    if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
-    {
-        /* Invalidate the back buffer memory so LockRect will read it the next time */
-        for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
-        {
             struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]);
             if (target)
             {
-                surface_load_location(target, target->container->resource.draw_binding);
+                surface_load_location(target, context, target->container->resource.draw_binding);
                 surface_invalidate_location(target, ~target->container->resource.draw_binding);
             }
         }
     }
 
-    context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]));
-    if (!context->valid)
-    {
-        context_release(context);
-        WARN("Invalid context, skipping draw.\n");
-        return;
-    }
-    gl_info = context->gl_info;
-
     if (device->fb.depth_stencil)
     {
         /* Note that this depends on the context_acquire() call above to set
index 70131e0..d4e36d9 100644 (file)
@@ -252,21 +252,18 @@ static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
 }
 
 static void (WINE_GLAPI *old_fogcoord_glVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glVertex4fv) (const GLfloat *pos) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glVertex3f) (GLfloat x, GLfloat y, GLfloat z) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glVertex3fv) (const GLfloat *pos) = NULL;
 static void (WINE_GLAPI *old_fogcoord_glColor4f) (GLfloat r, GLfloat g, GLfloat b, GLfloat a) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glColor4fv) (const GLfloat *color) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glColor3f) (GLfloat r, GLfloat g, GLfloat b) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glColor3fv) (const GLfloat *color) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glColor4ub) (GLubyte r, GLubyte g, GLubyte b, GLubyte a) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glFogCoordfEXT) (GLfloat f) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glFogCoorddEXT) (GLdouble f) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL;
-static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL;
 
 static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
     struct wined3d_context *ctx = context_get_current();
+
+    /* This can be called from draw_test_quad() and at that point there is no
+     * wined3d_context current. */
+    if (!ctx)
+    {
+        old_fogcoord_glVertex4f(x, y, z, w);
+        return;
+    }
     if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) {
         GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]};
         GLfloat i;
@@ -297,6 +294,14 @@ static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) {
 
 static void WINE_GLAPI wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
     struct wined3d_context *ctx = context_get_current();
+
+    /* This can be called from draw_test_quad() and at that point there is no
+     * wined3d_context current. */
+    if (!ctx)
+    {
+        old_fogcoord_glColor4f(r, g, b, a);
+        return;
+    }
     ctx->color[0] = r;
     ctx->color[1] = g;
     ctx->color[2] = b;
@@ -339,198 +344,117 @@ static void WINE_GLAPI wine_glFogCoorddvEXT(const GLdouble *f) {
 
 /* End GL_EXT_fog_coord emulation */
 
-void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info)
+void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext)
 {
-    if (!gl_info->supported[ARB_MULTITEXTURE])
+    switch (ext)
     {
-        TRACE("Applying GL_ARB_multitexture emulation hooks\n");
-        gl_info->gl_ops.ext.p_glActiveTexture           = wine_glActiveTexture;
-        gl_info->gl_ops.ext.p_glClientActiveTextureARB  = wine_glClientActiveTextureARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord1fARB      = wine_glMultiTexCoord1fARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord1fvARB     = wine_glMultiTexCoord1fvARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord2fARB      = wine_glMultiTexCoord2fARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord2fvARB     = wine_glMultiTexCoord2fvARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord3fARB      = wine_glMultiTexCoord3fARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord3fvARB     = wine_glMultiTexCoord3fvARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord4fARB      = wine_glMultiTexCoord4fARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord4fvARB     = wine_glMultiTexCoord4fvARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord2svARB     = wine_glMultiTexCoord2svARB;
-        gl_info->gl_ops.ext.p_glMultiTexCoord4svARB     = wine_glMultiTexCoord4svARB;
-        if(old_multitex_glGetIntegerv) {
-            FIXME("GL_ARB_multitexture glGetIntegerv hook already applied\n");
-        } else {
+        case ARB_MULTITEXTURE:
+            if (gl_info->supported[ARB_MULTITEXTURE])
+                return;
+            if (gl_info->gl_ops.ext.p_glActiveTexture == wine_glActiveTexture)
+            {
+                FIXME("ARB_multitexture emulation hooks already applied.\n");
+                return;
+            }
+            TRACE("Applying GL_ARB_multitexture emulation hooks.\n");
+            gl_info->gl_ops.ext.p_glActiveTexture           = wine_glActiveTexture;
+            gl_info->gl_ops.ext.p_glClientActiveTextureARB  = wine_glClientActiveTextureARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord1fARB      = wine_glMultiTexCoord1fARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord1fvARB     = wine_glMultiTexCoord1fvARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord2fARB      = wine_glMultiTexCoord2fARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord2fvARB     = wine_glMultiTexCoord2fvARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord3fARB      = wine_glMultiTexCoord3fARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord3fvARB     = wine_glMultiTexCoord3fvARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord4fARB      = wine_glMultiTexCoord4fARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord4fvARB     = wine_glMultiTexCoord4fvARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord2svARB     = wine_glMultiTexCoord2svARB;
+            gl_info->gl_ops.ext.p_glMultiTexCoord4svARB     = wine_glMultiTexCoord4svARB;
             old_multitex_glGetIntegerv = gl_info->gl_ops.gl.p_glGetIntegerv;
             gl_info->gl_ops.gl.p_glGetIntegerv = wine_glGetIntegerv;
-        }
-        if(old_multitex_glGetFloatv) {
-            FIXME("GL_ARB_multitexture glGetGloatv hook already applied\n");
-        } else {
             old_multitex_glGetFloatv = gl_info->gl_ops.gl.p_glGetFloatv;
             gl_info->gl_ops.gl.p_glGetFloatv = wine_glGetFloatv;
-        }
-        if(old_multitex_glGetDoublev) {
-            FIXME("GL_ARB_multitexture glGetDoublev hook already applied\n");
-        } else {
             old_multitex_glGetDoublev = gl_info->gl_ops.gl.p_glGetDoublev;
             gl_info->gl_ops.gl.p_glGetDoublev = wine_glGetDoublev;
-        }
-        gl_info->supported[ARB_MULTITEXTURE] = TRUE;
-    }
-
-    if (!gl_info->supported[EXT_FOG_COORD])
-    {
-        /* This emulation isn't perfect. There are a number of potential problems, but they should
-         * not matter in practise:
-         *
-         * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
-         * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
-         * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
-         * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
-         *
-         * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
-         * ignore the vertex color, thus effectively disabling our fog. However, in D3D this type of fog is
-         * a per-vertex fog too, so the apps shouldn't do that.
-         *
-         * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
-         * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
-         * calculations could affect the already blended in fog color. There's nothing we can do against that,
-         * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
-         * with it.
-         */
-        TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
-
-        /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
-         * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
-         * dependent loading for this extension if we ever hit this situation
-         */
-        if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
-        {
-            FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
-            FIXME("The fog coord emulation will most likely fail\n");
-        }
-        else if (gl_info->supported[ARB_FRAGMENT_SHADER])
-        {
-            FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
-            FIXME("The fog coord emulation will most likely fail\n");
-        }
+            gl_info->supported[ARB_MULTITEXTURE] = TRUE;
+            return;
+
+        case EXT_FOG_COORD:
+            /* This emulation isn't perfect. There are a number of potential problems, but they should
+             * not matter in practise:
+             *
+             * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
+             * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
+             * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
+             * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
+             *
+             * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
+             * ignore the vertex color, thus effectively disabling our fog. However, in D3D this type of fog is
+             * a per-vertex fog too, so the apps shouldn't do that.
+             *
+             * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
+             * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
+             * calculations could affect the already blended in fog color. There's nothing we can do against that,
+             * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
+             * with it.
+             */
+            if (gl_info->supported[EXT_FOG_COORD])
+                return;
+            if (gl_info->gl_ops.gl.p_glFogi == wine_glFogi)
+            {
+                FIXME("EXT_fog_coord emulation hooks already applied.\n");
+                return;
+            }
+            TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
+
+            /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
+             * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
+             * dependent loading for this extension if we ever hit this situation
+             */
+            if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+            {
+                FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
+                FIXME("The fog coord emulation will most likely fail\n");
+            }
+            else if (gl_info->supported[ARB_FRAGMENT_SHADER])
+            {
+                FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
+                FIXME("The fog coord emulation will most likely fail\n");
+            }
 
-        if(old_fogcoord_glFogi) {
-            FIXME("GL_EXT_fogcoord glFogi hook already applied\n");
-        } else {
             old_fogcoord_glFogi = gl_info->gl_ops.gl.p_glFogi;
             gl_info->gl_ops.gl.p_glFogi = wine_glFogi;
-        }
-        if(old_fogcoord_glFogiv) {
-            FIXME("GL_EXT_fogcoord glFogiv hook already applied\n");
-        } else {
             old_fogcoord_glFogiv = gl_info->gl_ops.gl.p_glFogiv;
             gl_info->gl_ops.gl.p_glFogiv = wine_glFogiv;
-        }
-        if(old_fogcoord_glFogf) {
-            FIXME("GL_EXT_fogcoord glFogf hook already applied\n");
-        } else {
             old_fogcoord_glFogf = gl_info->gl_ops.gl.p_glFogf;
             gl_info->gl_ops.gl.p_glFogf = wine_glFogf;
-        }
-        if(old_fogcoord_glFogfv) {
-            FIXME("GL_EXT_fogcoord glFogfv hook already applied\n");
-        } else {
             old_fogcoord_glFogfv = gl_info->gl_ops.gl.p_glFogfv;
             gl_info->gl_ops.gl.p_glFogfv = wine_glFogfv;
-        }
-        if(old_fogcoord_glEnable) {
-            FIXME("GL_EXT_fogcoord glEnable hook already applied\n");
-        } else {
             old_fogcoord_glEnable = glEnableWINE;
             glEnableWINE = wine_glEnable;
-        }
-        if(old_fogcoord_glDisable) {
-            FIXME("GL_EXT_fogcoord glDisable hook already applied\n");
-        } else {
             old_fogcoord_glDisable = glDisableWINE;
             glDisableWINE = wine_glDisable;
-        }
 
-        if(old_fogcoord_glVertex4f) {
-            FIXME("GL_EXT_fogcoord glVertex4f hook already applied\n");
-        } else {
             old_fogcoord_glVertex4f = gl_info->gl_ops.gl.p_glVertex4f;
             gl_info->gl_ops.gl.p_glVertex4f = wine_glVertex4f;
-        }
-        if(old_fogcoord_glVertex4fv) {
-            FIXME("GL_EXT_fogcoord glVertex4fv hook already applied\n");
-        } else {
-            old_fogcoord_glVertex4fv = gl_info->gl_ops.gl.p_glVertex4fv;
             gl_info->gl_ops.gl.p_glVertex4fv = wine_glVertex4fv;
-        }
-        if(old_fogcoord_glVertex3f) {
-            FIXME("GL_EXT_fogcoord glVertex3f hook already applied\n");
-        } else {
-            old_fogcoord_glVertex3f = gl_info->gl_ops.gl.p_glVertex3f;
             gl_info->gl_ops.gl.p_glVertex3f = wine_glVertex3f;
-        }
-        if(old_fogcoord_glVertex3fv) {
-            FIXME("GL_EXT_fogcoord glVertex3fv hook already applied\n");
-        } else {
-            old_fogcoord_glVertex3fv = gl_info->gl_ops.gl.p_glVertex3fv;
             gl_info->gl_ops.gl.p_glVertex3fv = wine_glVertex3fv;
-        }
 
-        if(old_fogcoord_glColor4f) {
-            FIXME("GL_EXT_fogcoord glColor4f hook already applied\n");
-        } else {
             old_fogcoord_glColor4f = gl_info->gl_ops.gl.p_glColor4f;
             gl_info->gl_ops.gl.p_glColor4f = wine_glColor4f;
-        }
-        if(old_fogcoord_glColor4fv) {
-            FIXME("GL_EXT_fogcoord glColor4fv hook already applied\n");
-        } else {
-            old_fogcoord_glColor4fv = gl_info->gl_ops.gl.p_glColor4fv;
             gl_info->gl_ops.gl.p_glColor4fv = wine_glColor4fv;
-        }
-        if(old_fogcoord_glColor3f) {
-            FIXME("GL_EXT_fogcoord glColor3f hook already applied\n");
-        } else {
-            old_fogcoord_glColor3f = gl_info->gl_ops.gl.p_glColor3f;
             gl_info->gl_ops.gl.p_glColor3f = wine_glColor3f;
-        }
-        if(old_fogcoord_glColor3fv) {
-            FIXME("GL_EXT_fogcoord glColor3fv hook already applied\n");
-        } else {
-            old_fogcoord_glColor3fv = gl_info->gl_ops.gl.p_glColor3fv;
             gl_info->gl_ops.gl.p_glColor3fv = wine_glColor3fv;
-        }
-        if(old_fogcoord_glColor4ub) {
-            FIXME("GL_EXT_fogcoord glColor4ub hook already applied\n");
-        } else {
-            old_fogcoord_glColor4ub = gl_info->gl_ops.gl.p_glColor4ub;
             gl_info->gl_ops.gl.p_glColor4ub = wine_glColor4ub;
-        }
 
-        if(old_fogcoord_glFogCoordfEXT) {
-            FIXME("GL_EXT_fogcoord glFogCoordfEXT hook already applied\n");
-        } else {
-            old_fogcoord_glFogCoordfEXT = gl_info->gl_ops.ext.p_glFogCoordfEXT;
             gl_info->gl_ops.ext.p_glFogCoordfEXT = wine_glFogCoordfEXT;
-        }
-        if(old_fogcoord_glFogCoordfvEXT) {
-            FIXME("GL_EXT_fogcoord glFogCoordfvEXT hook already applied\n");
-        } else {
-            old_fogcoord_glFogCoordfvEXT = gl_info->gl_ops.ext.p_glFogCoordfvEXT;
             gl_info->gl_ops.ext.p_glFogCoordfvEXT = wine_glFogCoordfvEXT;
-        }
-        if(old_fogcoord_glFogCoorddEXT) {
-            FIXME("GL_EXT_fogcoord glFogCoorddEXT hook already applied\n");
-        } else {
-            old_fogcoord_glFogCoorddEXT = gl_info->gl_ops.ext.p_glFogCoorddEXT;
             gl_info->gl_ops.ext.p_glFogCoorddEXT = wine_glFogCoorddEXT;
-        }
-        if(old_fogcoord_glFogCoorddvEXT) {
-            FIXME("GL_EXT_fogcoord glFogCoorddvEXT hook already applied\n");
-        } else {
-            old_fogcoord_glFogCoorddvEXT = gl_info->gl_ops.ext.p_glFogCoorddvEXT;
             gl_info->gl_ops.ext.p_glFogCoorddvEXT = wine_glFogCoorddvEXT;
-        }
-        gl_info->supported[EXT_FOG_COORD] = TRUE;
+            gl_info->supported[EXT_FOG_COORD] = TRUE;
+            return;
+
+        default:
+            FIXME("Extension %u emulation not supported.\n", ext);
     }
 }
index 8eb2d3c..c563274 100644 (file)
@@ -57,6 +57,7 @@ struct glsl_sample_function
     struct wined3d_string_buffer *name;
     DWORD coord_mask;
     enum wined3d_data_type data_type;
+    BOOL output_single_component;
 };
 
 enum heap_node_op
@@ -324,7 +325,7 @@ static const char *get_info_log_line(const char **ptr)
 }
 
 /* Context activation is done by the caller. */
-static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
+void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
 {
     int length = 0;
     char *log;
@@ -444,7 +445,7 @@ static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_inf
 }
 
 /* Context activation is done by the caller. */
-static void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program)
+void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program)
 {
     GLint tmp;
 
@@ -1257,12 +1258,11 @@ static void shader_glsl_load_fog_uniform(const struct wined3d_context *context,
 static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps,
         const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
 {
-    struct wined3d_color float_key;
+    struct wined3d_color float_key[2];
     const struct wined3d_texture *texture = state->textures[0];
 
-    wined3d_format_convert_color_to_float(texture->resource.format, NULL,
-            texture->async.src_blt_color_key.color_space_high_value, &float_key);
-    GL_EXTCALL(glUniform4fv(ps->color_key_location, 1, &float_key.r));
+    wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key);
+    GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r));
 }
 
 /* Context activation is done by the caller (state handler). */
@@ -1533,6 +1533,80 @@ static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_in
     return ret;
 }
 
+static BOOL needs_legacy_glsl_syntax(const struct wined3d_gl_info *gl_info)
+{
+    return gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
+}
+
+static void PRINTF_ATTR(4, 5) declare_in_varying(const struct wined3d_gl_info *gl_info,
+        struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
+{
+    va_list args;
+    int ret;
+
+    shader_addline(buffer, "%s%s ", flat ? "flat " : "",
+            needs_legacy_glsl_syntax(gl_info) ? "varying" : "in");
+    for (;;)
+    {
+        va_start(args, format);
+        ret = shader_vaddline(buffer, format, args);
+        va_end(args);
+        if (!ret)
+            return;
+        if (!string_buffer_resize(buffer, ret))
+            return;
+    }
+}
+
+static void PRINTF_ATTR(4, 5) declare_out_varying(const struct wined3d_gl_info *gl_info,
+        struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
+{
+    va_list args;
+    int ret;
+
+    shader_addline(buffer, "%s%s ", flat ? "flat " : "",
+            needs_legacy_glsl_syntax(gl_info) ? "varying" : "out");
+    for (;;)
+    {
+        va_start(args, format);
+        ret = shader_vaddline(buffer, format, args);
+        va_end(args);
+        if (!ret)
+            return;
+        if (!string_buffer_resize(buffer, ret))
+            return;
+    }
+}
+
+static BOOL glsl_is_color_reg_read(const struct wined3d_shader *shader, unsigned int idx)
+{
+    const struct wined3d_shader_signature *input_signature = &shader->input_signature;
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const BOOL *input_reg_used = shader->u.ps.input_reg_used;
+    unsigned int i;
+
+    if (reg_maps->shader_version.major < 3)
+        return input_reg_used[idx];
+
+    for (i = 0; i < input_signature->element_count; ++i)
+    {
+        const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
+
+        if (!(reg_maps->input_registers & (1u << input->register_idx)))
+            continue;
+
+        if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_COLOR)
+                && input->semantic_idx == idx)
+        {
+            if (input_reg_used[input->register_idx])
+                return TRUE;
+            else
+                return FALSE;
+        }
+    }
+    return FALSE;
+}
+
 /** Generate the variable & register declarations for the GLSL output target */
 static void shader_generate_glsl_declarations(const struct wined3d_context *context,
         struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
@@ -1605,10 +1679,8 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
                  * Writing gl_ClipVertex requires one uniform for each
                  * clipplane as well. */
                 max_constantsF = gl_info->limits.glsl_vs_float_constants - 3;
-                if(ctx_priv->cur_vs_args->clip_enabled)
-                {
+                if (vs_args->clip_enabled)
                     max_constantsF -= gl_info->limits.clipplanes;
-                }
                 max_constantsF -= count_bits(reg_maps->integer_constants);
                 /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
                  * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
@@ -1669,7 +1741,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
             continue;
         }
 
-        shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1 << entry->sampler_idx));
+        shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1u << entry->sampler_idx));
         switch (reg_maps->resource_info[entry->resource_idx].type)
         {
             case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
@@ -1681,7 +1753,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
 
             case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
                 tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL
-                        && (ps_args->np2_fixup & (1 << entry->resource_idx))
+                        && (ps_args->np2_fixup & (1u << entry->resource_idx))
                         && gl_info->supported[ARB_TEXTURE_RECTANGLE];
                 if (shadow_sampler)
                 {
@@ -1736,7 +1808,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
 
         for (i = 0; i < shader->limits->sampler; ++i)
         {
-            if (!reg_maps->resource_info[i].type || !(ps_args->np2_fixup & (1 << i)))
+            if (!reg_maps->resource_info[i].type || !(ps_args->np2_fixup & (1u << i)))
                 continue;
 
             if (reg_maps->resource_info[i].type != WINED3D_SHADER_RESOURCE_TEXTURE_2D)
@@ -1759,12 +1831,6 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i);
     }
 
-    /* Declare texture coordinate temporaries and initialize them */
-    for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i)
-    {
-        if (map & 1) shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i);
-    }
-
     if (version->type == WINED3D_SHADER_TYPE_VERTEX)
     {
         for (i = 0; i < shader->input_signature.element_count; ++i)
@@ -1786,6 +1852,14 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
             shader_addline(buffer, "} ffp_point;\n");
         }
 
+        if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] && version->major < 3)
+        {
+            declare_out_varying(gl_info, buffer, vs_args->flatshading, "vec4 ffp_varying_diffuse;\n");
+            declare_out_varying(gl_info, buffer, vs_args->flatshading, "vec4 ffp_varying_specular;\n");
+            declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
+            declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
+        }
+
         shader_addline(buffer, "uniform vec4 posFixup;\n");
         shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", shader->limits->packed_output);
     }
@@ -1803,6 +1877,26 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
             shader_addline(buffer, "    float end;\n");
             shader_addline(buffer, "    float scale;\n");
             shader_addline(buffer, "} ffp_fog;\n");
+
+            if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+            {
+                if (glsl_is_color_reg_read(shader, 0))
+                    shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
+                if (glsl_is_color_reg_read(shader, 1))
+                    shader_addline(buffer, "vec4 ffp_varying_specular;\n");
+                shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
+                shader_addline(buffer, "float ffp_varying_fogcoord;\n");
+            }
+            else
+            {
+                if (glsl_is_color_reg_read(shader, 0))
+                    declare_in_varying(gl_info, buffer, ps_args->flatshading, "vec4 ffp_varying_diffuse;\n");
+                if (glsl_is_color_reg_read(shader, 1))
+                    declare_in_varying(gl_info, buffer, ps_args->flatshading, "vec4 ffp_varying_specular;\n");
+                declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
+                shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
+                declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
+            }
         }
 
         if (version->major >= 3)
@@ -1814,7 +1908,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
 #else  /* STAGING_CSMT */
             if (use_vs(state))
 #endif /* STAGING_CSMT */
-                shader_addline(buffer, "varying vec4 %s_link[%u];\n", prefix, in_count);
+                declare_in_varying(gl_info, buffer, FALSE, "vec4 %s_link[%u];\n", prefix, in_count);
             shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count);
         }
 
@@ -1825,7 +1919,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
 
             shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", i);
 
-            if (reg_maps->luminanceparams & (1 << i))
+            if (reg_maps->luminanceparams & (1u << i))
             {
                 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", i);
                 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", i);
@@ -2064,7 +2158,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
             if (version->type == WINED3D_SHADER_TYPE_VERTEX)
             {
                 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
-                if (priv->cur_vs_args->swizzle_map & (1 << reg->idx[0].offset))
+                if (priv->cur_vs_args->swizzle_map & (1u << reg->idx[0].offset))
                     *is_color = TRUE;
                 sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset);
                 break;
@@ -2101,7 +2195,8 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
                      * OS X doesn't see the NOP operation there. */
                     if (idx)
                     {
-                        if (shader->u.ps.declared_in_count > in_count)
+                        if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]
+                                && shader->u.ps.declared_in_count > in_count)
                         {
                             sprintf(register_name,
                                     "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])",
@@ -2115,7 +2210,8 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
                     }
                     else
                     {
-                        if (shader->u.ps.declared_in_count > in_count)
+                        if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]
+                                && shader->u.ps.declared_in_count > in_count)
                         {
                             sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])",
                                     rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count,
@@ -2137,9 +2233,9 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
             else
             {
                 if (!reg->idx[0].offset)
-                    strcpy(register_name, "gl_Color");
+                    strcpy(register_name, "ffp_varying_diffuse");
                 else
-                    strcpy(register_name, "gl_SecondaryColor");
+                    strcpy(register_name, "ffp_varying_specular");
                 break;
             }
             break;
@@ -2552,7 +2648,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type;
     const struct wined3d_gl_info *gl_info = ctx->gl_info;
     BOOL shadow = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
-            && (priv->cur_ps_args->shadow & (1 << resource_idx));
+            && (priv->cur_ps_args->shadow & (1u << resource_idx));
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
     BOOL texrect = flags & WINED3D_GLSL_SAMPLE_NPOT && gl_info->supported[ARB_TEXTURE_RECTANGLE];
     BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
@@ -2572,21 +2668,24 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
         projected = FALSE;
 
-    if (shadow)
-        base = "shadow";
+    if (needs_legacy_glsl_syntax(gl_info))
+    {
+        if (shadow)
+            base = "shadow";
 
-    type_part = resource_types[resource_type].type_part;
-    if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect)
-        type_part = "2DRect";
-    if (!type_part[0])
-        FIXME("Unhandled resource type %#x.\n", resource_type);
+        type_part = resource_types[resource_type].type_part;
+        if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect)
+            type_part = "2DRect";
+        if (!type_part[0])
+            FIXME("Unhandled resource type %#x.\n", resource_type);
 
-    if (!lod && grad && !gl_info->supported[EXT_GPU_SHADER4])
-    {
-        if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-            suffix = "ARB";
-        else
-            FIXME("Unsupported grad function.\n");
+        if (!lod && grad && !gl_info->supported[EXT_GPU_SHADER4])
+        {
+            if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                suffix = "ARB";
+            else
+                FIXME("Unsupported grad function.\n");
+        }
     }
 
     sample_function->name = string_buffer_get(priv->string_buffers);
@@ -2596,7 +2695,8 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     coord_size = resource_types[resource_type].coord_size;
     if (shadow)
         ++coord_size;
-    sample_function->coord_mask = (1 << coord_size) - 1;
+    sample_function->coord_mask = (1u << coord_size) - 1;
+    sample_function->output_single_component = shadow && !needs_legacy_glsl_syntax(gl_info);
 }
 
 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx,
@@ -2733,7 +2833,7 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s
         const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
         fixup = priv->cur_ps_args->color_fixup[sampler];
 
-        if (priv->cur_ps_args->np2_fixup & (1 << sampler))
+        if (priv->cur_ps_args->np2_fixup & (1u << sampler))
             np2_fixup = TRUE;
     }
     else
@@ -2743,6 +2843,9 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s
 
     shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], sample_function->data_type);
 
+    if (sample_function->output_single_component)
+        shader_addline(ins->ctx->buffer, "vec4(");
+
     shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ",
             sample_function->name->buffer, shader_glsl_get_prefix(version->type), sampler);
 
@@ -2789,6 +2892,9 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s
     else
         shader_addline(ins->ctx->buffer, ")");
 
+    if (sample_function->output_single_component)
+        shader_addline(ins->ctx->buffer, ")");
+
     shader_addline(ins->ctx->buffer, "%s);\n", dst_swizzle);
 
     if (!is_identity_fixup(fixup))
@@ -4019,7 +4125,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
         }
     }
 
-    if (priv->cur_ps_args->np2_fixup & (1 << resource_idx))
+    if (priv->cur_ps_args->np2_fixup & (1u << resource_idx))
         sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, resource_idx, sample_flags, &sample_function);
@@ -4074,7 +4180,7 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
     }
 
     sampler_idx = ins->src[1].reg.idx[0].offset;
-    if (priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+    if (priv->cur_ps_args->np2_fixup & (1u << sampler_idx))
         sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
@@ -4099,7 +4205,7 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
 
     sampler_idx = ins->src[1].reg.idx[0].offset;
     if (ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
-            && priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+            && priv->cur_ps_args->np2_fixup & (1u << sampler_idx))
         sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
@@ -4163,7 +4269,7 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
         char dst_mask[6];
 
         shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
-        shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n",
+        shader_addline(buffer, "clamp(ffp_texcoord[%u], 0.0, 1.0)%s);\n",
                 ins->dst[0].reg.idx[0].offset, dst_mask);
     }
     else
@@ -4174,33 +4280,22 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
 
         shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
 
-        if (src_mod == WINED3DSPSM_DZ)
+        if (src_mod == WINED3DSPSM_DZ || src_mod == WINED3DSPSM_DW)
         {
             unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
             struct glsl_src_param div_param;
+            DWORD src_writemask = src_mod == WINED3DSPSM_DZ ? WINED3DSP_WRITEMASK_2 : WINED3DSP_WRITEMASK_3;
 
-            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &div_param);
+            shader_glsl_add_src_param(ins, &ins->src[0], src_writemask, &div_param);
 
-            if (mask_size > 1) {
-                shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
-            } else {
-                shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
-            }
+            if (mask_size > 1)
+                shader_addline(buffer, "ffp_texcoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
+            else
+                shader_addline(buffer, "ffp_texcoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
         }
-        else if (src_mod == WINED3DSPSM_DW)
+        else
         {
-            unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
-            struct glsl_src_param div_param;
-
-            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &div_param);
-
-            if (mask_size > 1) {
-                shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
-            } else {
-                shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
-            }
-        } else {
-            shader_addline(buffer, "gl_TexCoord[%u]%s);\n", reg, dst_swizzle);
+            shader_addline(buffer, "ffp_texcoord[%u]%s);\n", reg, dst_swizzle);
         }
     }
 }
@@ -4230,17 +4325,17 @@ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
     {
         case 1:
             shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    "dot(gl_TexCoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
+                    "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
             break;
 
         case 2:
             shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    "vec2(dot(gl_TexCoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
+                    "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
             break;
 
         case 3:
             shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
-                    "vec3(dot(gl_TexCoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
+                    "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
             break;
 
         default:
@@ -4445,7 +4540,7 @@ static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *in
     shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
 
     /* Construct the eye-ray vector from w coordinates */
-    shader_addline(buffer, "tmp1.xyz = normalize(vec3(gl_TexCoord[%u].w, gl_TexCoord[%u].w, gl_TexCoord[%u].w));\n",
+    shader_addline(buffer, "tmp1.xyz = normalize(vec3(ffp_texcoord[%u].w, ffp_texcoord[%u].w, ffp_texcoord[%u].w));\n",
             tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg);
     shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n");
 
@@ -4653,7 +4748,7 @@ static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins)
 static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer,
         const struct wined3d_shader_signature *input_signature,
         const struct wined3d_shader_reg_maps *reg_maps,
-        const struct ps_compile_args *args)
+        const struct ps_compile_args *args, const struct wined3d_gl_info *gl_info)
 {
     unsigned int i;
 
@@ -4665,7 +4760,7 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
         char reg_mask[6];
 
         /* Unused */
-        if (!(reg_maps->input_registers & (1 << input->register_idx)))
+        if (!(reg_maps->input_registers & (1u << input->register_idx)))
             continue;
 
         semantic_name = input->semantic_name;
@@ -4686,9 +4781,14 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
         }
         else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
         {
-            if (semantic_idx < 8 && args->vp_mode == pretransformed)
-                shader_addline(buffer, "ps_in[%u]%s = gl_TexCoord[%u]%s;\n",
-                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, semantic_idx, reg_mask);
+            if (args->pointsprite)
+                shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n",
+                        shader->u.ps.input_reg_map[input->register_idx]);
+            else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx))
+                shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n",
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask,
+                        gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]
+                        ? "gl_TexCoord" : "ffp_varying_texcoord", semantic_idx, reg_mask);
             else
                 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
                         shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
@@ -4696,10 +4796,10 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
         else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
         {
             if (!semantic_idx)
-                shader_addline(buffer, "ps_in[%u]%s = vec4(gl_Color)%s;\n",
+                shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_diffuse)%s;\n",
                         shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
             else if (semantic_idx == 1)
-                shader_addline(buffer, "ps_in[%u]%s = vec4(gl_SecondaryColor)%s;\n",
+                shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_specular)%s;\n",
                         shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
             else
                 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
@@ -4776,27 +4876,29 @@ static void handle_ps3_input(struct shader_glsl_priv *priv,
         const struct wined3d_shader_reg_maps *reg_maps_out)
 {
     struct wined3d_string_buffer *buffer = &priv->shader_buffer;
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
     unsigned int i, j;
     DWORD *set;
     DWORD in_idx;
     unsigned int in_count = vec4_varyings(3, gl_info);
+    unsigned int max_varyings = legacy_context ? in_count + 2 : in_count;
     char reg_mask[6];
     struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers);
 
-    set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2));
+    set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * max_varyings);
 
     for (i = 0; i < input_signature->element_count; ++i)
     {
         const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
 
-        if (!(reg_maps_in->input_registers & (1 << input->register_idx)))
+        if (!(reg_maps_in->input_registers & (1u << input->register_idx)))
             continue;
 
         in_idx = map[input->register_idx];
         /* Declared, but not read register */
         if (in_idx == ~0u)
             continue;
-        if (in_idx >= (in_count + 2))
+        if (in_idx >= max_varyings)
         {
             FIXME("More input varyings declared than supported, expect issues.\n");
             continue;
@@ -4817,16 +4919,15 @@ static void handle_ps3_input(struct shader_glsl_priv *priv,
             const struct wined3d_shader_signature_element *output = &output_signature->elements[j];
             DWORD mask;
 
-            if (!(reg_maps_out->output_registers & (1 << output->register_idx))
+            if (!(reg_maps_out->output_registers & (1u << output->register_idx))
                     || input->semantic_idx != output->semantic_idx
                     || strcmp(input->semantic_name, output->semantic_name)
                     || !(mask = input->mask & output->mask))
                 continue;
 
             if (set[in_idx] == ~0u)
-                set[in_idx] = mask;
-            else
-                set[in_idx] |= mask;
+                set[in_idx] = 0;
+            set[in_idx] |= mask & reg_maps_out->u.output_registers_mask[output->register_idx];
             shader_glsl_write_mask_to_str(mask, reg_mask);
 
             shader_addline(buffer, "%s%s = vs_out[%u]%s;\n",
@@ -4834,7 +4935,7 @@ static void handle_ps3_input(struct shader_glsl_priv *priv,
         }
     }
 
-    for (i = 0; i < in_count + 2; ++i)
+    for (i = 0; i < max_varyings; ++i)
     {
         unsigned int size;
 
@@ -4868,7 +4969,7 @@ static void handle_ps3_input(struct shader_glsl_priv *priv,
 /* Context activation is done by the caller. */
 static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
         const struct wined3d_shader *vs, const struct wined3d_shader *ps,
-        BOOL per_vertex_point_size, const struct wined3d_gl_info *gl_info)
+        BOOL per_vertex_point_size, BOOL flatshading, const struct wined3d_gl_info *gl_info)
 {
     struct wined3d_string_buffer *buffer = &priv->shader_buffer;
     GLuint ret = 0;
@@ -4877,6 +4978,7 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
     const char *semantic_name;
     UINT semantic_idx;
     char reg_mask[6];
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
 
     string_buffer_clear(buffer);
 
@@ -4892,6 +4994,17 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
 
     if (ps_major < 3)
     {
+        DWORD colors_written_mask[2] = {0};
+        DWORD texcoords_written_mask[MAX_TEXTURES] = {0};
+
+        if (!legacy_context)
+        {
+            declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_diffuse;\n");
+            declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_specular;\n");
+            declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
+            declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n");
+        }
+
         shader_addline(buffer, "void order_ps_input(in vec4 vs_out[%u])\n{\n", vs->limits->packed_output);
 
         for (i = 0; i < vs->output_signature.element_count; ++i)
@@ -4899,7 +5012,7 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
             const struct wined3d_shader_signature_element *output = &vs->output_signature.elements[i];
             DWORD write_mask;
 
-            if (!(vs->reg_maps.output_registers & (1 << output->register_idx)))
+            if (!(vs->reg_maps.output_registers & (1u << output->register_idx)))
                 continue;
 
             semantic_name = output->semantic_name;
@@ -4907,14 +5020,16 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
             write_mask = output->mask;
             shader_glsl_write_mask_to_str(write_mask, reg_mask);
 
-            if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+            if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR) && semantic_idx < 2)
             {
-                if (!semantic_idx)
-                    shader_addline(buffer, "gl_FrontColor%s = vs_out[%u]%s;\n",
-                            reg_mask, output->register_idx, reg_mask);
-                else if (semantic_idx == 1)
-                    shader_addline(buffer, "gl_FrontSecondaryColor%s = vs_out[%u]%s;\n",
-                            reg_mask, output->register_idx, reg_mask);
+                if (legacy_context)
+                    shader_addline(buffer, "gl_Front%sColor%s = vs_out[%u]%s;\n",
+                            semantic_idx ? "Secondary" : "", reg_mask, output->register_idx, reg_mask);
+                else
+                    shader_addline(buffer, "ffp_varying_%s%s = clamp(vs_out[%u]%s, 0.0, 1.0);\n",
+                            semantic_idx ? "specular" : "diffuse", reg_mask, output->register_idx, reg_mask);
+
+                colors_written_mask[semantic_idx] = write_mask;
             }
             else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION) && !semantic_idx)
             {
@@ -4923,15 +5038,12 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
             }
             else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
             {
-                if (semantic_idx < 8)
+                if (semantic_idx < MAX_TEXTURES)
                 {
-                    if (!(gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) || ps_major > 0)
-                        write_mask |= WINED3DSP_WRITEMASK_3;
-
-                    shader_addline(buffer, "gl_TexCoord[%u]%s = vs_out[%u]%s;\n",
+                    shader_addline(buffer, "%s[%u]%s = vs_out[%u]%s;\n",
+                            legacy_context ? "gl_TexCoord" : "ffp_varying_texcoord",
                             semantic_idx, reg_mask, output->register_idx, reg_mask);
-                    if (!(write_mask & WINED3DSP_WRITEMASK_3))
-                        shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx);
+                    texcoords_written_mask[semantic_idx] = write_mask;
                 }
             }
             else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size)
@@ -4941,17 +5053,49 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
             }
             else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
             {
-                shader_addline(buffer, "gl_FogFragCoord = clamp(vs_out[%u].%c, 0.0, 1.0);\n",
+                shader_addline(buffer, "%s = clamp(vs_out[%u].%c, 0.0, 1.0);\n",
+                        legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord",
                         output->register_idx, reg_mask[1]);
             }
         }
-        shader_addline(buffer, "}\n");
+
+        for (i = 0; i < 2; ++i)
+        {
+            if (colors_written_mask[i] != WINED3DSP_WRITEMASK_ALL)
+            {
+                shader_glsl_write_mask_to_str(~colors_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask);
+                if (!i)
+                    shader_addline(buffer, "%s%s = vec4(1.0)%s;\n",
+                            legacy_context ? "gl_FrontColor" : "ffp_varying_diffuse",
+                            reg_mask, reg_mask);
+                else
+                    shader_addline(buffer, "%s%s = vec4(0.0)%s;\n",
+                            legacy_context ? "gl_FrontSecondaryColor" : "ffp_varying_specular",
+                            reg_mask, reg_mask);
+            }
+        }
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            if (ps && !(ps->reg_maps.texcoord & (1u << i)))
+                continue;
+
+            if (texcoords_written_mask[i] != WINED3DSP_WRITEMASK_ALL)
+            {
+                if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info)
+                        && !texcoords_written_mask[i])
+                    continue;
+
+                shader_glsl_write_mask_to_str(~texcoords_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask);
+                shader_addline(buffer, "%s[%u]%s = vec4(0.0)%s;\n",
+                        legacy_context ? "gl_TexCoord" : "ffp_varying_texcoord", i, reg_mask, reg_mask);
+            }
+        }
     }
     else
     {
         UINT in_count = min(vec4_varyings(ps_major, gl_info), ps->limits->packed_input);
-        /* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */
-        shader_addline(buffer, "varying vec4 ps_link[%u];\n", in_count);
+
+        declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", in_count);
         shader_addline(buffer, "void order_ps_input(in vec4 vs_out[%u])\n{\n", vs->limits->packed_output);
 
         /* First, sort out position and point size. Those are not passed to the pixel shader */
@@ -4959,7 +5103,7 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
         {
             const struct wined3d_shader_signature_element *output = &vs->output_signature.elements[i];
 
-            if (!(vs->reg_maps.output_registers & (1 << output->register_idx)))
+            if (!(vs->reg_maps.output_registers & (1u << output->register_idx)))
                 continue;
 
             semantic_name = output->semantic_name;
@@ -4981,10 +5125,10 @@ static GLuint generate_param_reorder_function(struct shader_glsl_priv *priv,
         /* Then, fix the pixel shader input */
         handle_ps3_input(priv, gl_info, ps->u.ps.input_reg_map, &ps->input_signature,
                 &ps->reg_maps, &vs->output_signature, &vs->reg_maps);
-
-        shader_addline(buffer, "}\n");
     }
 
+    shader_addline(buffer, "}\n");
+
     ret = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
     checkGLcall("glCreateShader(GL_VERTEX_SHADER)");
     shader_glsl_compile(gl_info, ret, buffer->buffer);
@@ -5010,16 +5154,16 @@ static void shader_glsl_generate_fog_code(struct wined3d_string_buffer *buffer,
             return;
 
         case WINED3D_FFP_PS_FOG_LINEAR:
-            shader_addline(buffer, "float fog = (ffp_fog.end - gl_FogFragCoord) * ffp_fog.scale;\n");
+            shader_addline(buffer, "float fog = (ffp_fog.end - ffp_varying_fogcoord) * ffp_fog.scale;\n");
             break;
 
         case WINED3D_FFP_PS_FOG_EXP:
-            shader_addline(buffer, "float fog = exp(-ffp_fog.density * gl_FogFragCoord);\n");
+            shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_varying_fogcoord);\n");
             break;
 
         case WINED3D_FFP_PS_FOG_EXP2:
             shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_fog.density"
-                    " * gl_FogFragCoord * gl_FogFragCoord);\n");
+                    " * ffp_varying_fogcoord * ffp_varying_fogcoord);\n");
             break;
 
         default:
@@ -5041,6 +5185,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const DWORD *function = shader->function;
     struct shader_glsl_ctx_priv priv_ctx;
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
 
     /* Create the hw GLSL shader object and assign it as the shader->prgId */
     GLuint shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
@@ -5068,9 +5213,41 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
     /* Base Declarations */
     shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
 
+    if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader)
+    {
+        unsigned int i;
+        WORD map = reg_maps->texcoord;
+
+        if (legacy_context)
+        {
+            if (glsl_is_color_reg_read(shader, 0))
+                shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n");
+            if (glsl_is_color_reg_read(shader, 1))
+                shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n");
+        }
+
+        for (i = 0; map; map >>= 1, ++i)
+        {
+            if (map & 1)
+            {
+                if (args->pointsprite)
+                    shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", i);
+                else if (args->texcoords_initialized & (1u << i))
+                    shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", i,
+                            legacy_context ? "gl_TexCoord" : "ffp_varying_texcoord", i);
+                else
+                    shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", i);
+                shader_addline(buffer, "vec4 T%u = ffp_texcoord[%u];\n", i, i);
+            }
+        }
+
+        if (legacy_context)
+            shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n");
+    }
+
     /* Pack 3.0 inputs */
     if (reg_maps->shader_version.major >= 3)
-        shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args);
+        shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info);
 
     /* Base Shader Body */
     shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
@@ -5107,6 +5284,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const DWORD *function = shader->function;
     struct shader_glsl_ctx_priv priv_ctx;
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
 
     /* Create the hw GLSL shader program and assign it as the shader->prgId */
     GLuint shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
@@ -5140,10 +5318,15 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
      * the fog frag coord is thrown away. If the fog frag coord is used, but not written by
      * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
      */
-    if (args->fog_src == VS_FOG_Z)
-        shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
-    else if (!reg_maps->fog)
-        shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
+    if (reg_maps->shader_version.major < 3)
+    {
+        if (args->fog_src == VS_FOG_Z)
+            shader_addline(buffer, "%s = gl_Position.z;\n",
+                    legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
+        else if (!reg_maps->fog)
+            shader_addline(buffer, "%s = 0.0;\n",
+                    legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
+    }
 
     /* We always store the clipplanes without y inversion */
     if (args->clip_enabled)
@@ -5299,6 +5482,8 @@ static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const str
         return FALSE;
     if (stored->per_vertex_point_size != new->per_vertex_point_size)
         return FALSE;
+    if (stored->flatshading != new->flatshading)
+        return FALSE;
     return stored->fog_src == new->fog_src;
 }
 
@@ -5433,8 +5618,8 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
 
     if (!settings->lighting)
     {
-        shader_addline(buffer, "gl_FrontColor = ffp_attrib_diffuse;\n");
-        shader_addline(buffer, "gl_FrontSecondaryColor = ffp_attrib_specular;\n");
+        shader_addline(buffer, "ffp_varying_diffuse = ffp_attrib_diffuse;\n");
+        shader_addline(buffer, "ffp_varying_specular = ffp_attrib_specular;\n");
         return;
     }
 
@@ -5576,16 +5761,15 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
         }
     }
 
-    shader_addline(buffer, "gl_FrontColor.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
+    shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
             ambient, diffuse, emissive);
-    shader_addline(buffer, "gl_FrontColor.w = %s.w;\n", diffuse);
-    shader_addline(buffer, "gl_FrontSecondaryColor = %s * specular;\n", specular);
+    shader_addline(buffer, "ffp_varying_diffuse.w = %s.w;\n", diffuse);
+    shader_addline(buffer, "ffp_varying_specular = %s * specular;\n", specular);
 }
 
 /* Context activation is done by the caller. */
-static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffer *buffer,
-        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info,
-        BOOL legacy_lighting)
+static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *priv,
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
 {
     static const struct attrib_info
     {
@@ -5603,8 +5787,12 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe
         {"vec4", "ffp_attrib_diffuse"},         /* WINED3D_FFP_DIFFUSE */
         {"vec4", "ffp_attrib_specular"},        /* WINED3D_FFP_SPECULAR */
     };
+    struct wined3d_string_buffer *buffer = &priv->shader_buffer;
+    BOOL legacy_lighting = priv->legacy_lighting;
     GLuint shader_obj;
     unsigned int i;
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
+    BOOL output_legacy_fogcoord = legacy_context;
 
     string_buffer_clear(buffer);
 
@@ -5659,6 +5847,21 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe
         shader_addline(buffer, "} ffp_point;\n");
     }
 
+    if (legacy_context)
+    {
+        shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
+        shader_addline(buffer, "vec4 ffp_varying_specular;\n");
+        shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES);
+        shader_addline(buffer, "float ffp_varying_fogcoord;\n");
+    }
+    else
+    {
+        declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n");
+        declare_out_varying(gl_info, buffer, settings-