[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->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, "\nvoid main()\n{\n");
     shader_addline(buffer, "float m;\n");
     shader_addline(buffer, "vec3 r;\n");
@@ -5719,34 +5922,45 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe
     }
 
     shader_glsl_ffp_vertex_lighting(buffer, settings, legacy_lighting);
+    if (legacy_context)
+    {
+        shader_addline(buffer, "gl_FrontColor = ffp_varying_diffuse;\n");
+        shader_addline(buffer, "gl_FrontSecondaryColor = ffp_varying_specular;\n");
+    }
 
     for (i = 0; i < MAX_TEXTURES; ++i)
     {
+        BOOL output_legacy_texcoord = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
+
         switch (settings->texgen[i] & 0xffff0000)
         {
             case WINED3DTSS_TCI_PASSTHRU:
-                if (settings->texcoords & (1 << i))
-                    shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n",
+                if (settings->texcoords & (1u << i))
+                    shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n",
                             i, i, i);
+                else if (gl_info->limits.glsl_varyings >= wined3d_max_compat_varyings(gl_info))
+                    shader_addline(buffer, "ffp_varying_texcoord[%u] = vec4(0.0);\n", i);
+                else
+                    output_legacy_texcoord = FALSE;
                 break;
 
             case WINED3DTSS_TCI_CAMERASPACENORMAL:
-                shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u] * vec4(normal, 1.0);\n", i, i);
+                shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * vec4(normal, 1.0);\n", i, i);
                 break;
 
             case WINED3DTSS_TCI_CAMERASPACEPOSITION:
-                shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u] * ec_pos;\n", i, i);
+                shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ec_pos;\n", i, i);
                 break;
 
             case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
-                shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u]"
+                shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]"
                         " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i);
                 break;
 
             case WINED3DTSS_TCI_SPHEREMAP:
                 shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n");
                 shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n");
-                shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u]"
+                shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]"
                         " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i);
                 break;
 
@@ -5754,35 +5968,40 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe
                 ERR("Unhandled texgen %#x.\n", settings->texgen[i]);
                 break;
         }
+        if (output_legacy_texcoord)
+            shader_addline(buffer, "gl_TexCoord[%u] = ffp_varying_texcoord[%u];\n", i, i);
     }
 
     switch (settings->fog_mode)
     {
         case WINED3D_FFP_VS_FOG_OFF:
+            output_legacy_fogcoord = FALSE;
             break;
 
         case WINED3D_FFP_VS_FOG_FOGCOORD:
-            shader_addline(buffer, "gl_FogFragCoord = ffp_attrib_specular.w * 255.0;\n");
+            shader_addline(buffer, "ffp_varying_fogcoord = ffp_attrib_specular.w * 255.0;\n");
             break;
 
         case WINED3D_FFP_VS_FOG_RANGE:
-            shader_addline(buffer, "gl_FogFragCoord = length(ec_pos.xyz);\n");
+            shader_addline(buffer, "ffp_varying_fogcoord = length(ec_pos.xyz);\n");
             break;
 
         case WINED3D_FFP_VS_FOG_DEPTH:
             if (settings->ortho_fog)
                 /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */
-                shader_addline(buffer, "gl_FogFragCoord = gl_Position.z * 0.5 + 0.5;\n");
+                shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n");
             else if (settings->transformed)
-                shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n");
+                shader_addline(buffer, "ffp_varying_fogcoord = ec_pos.z;\n");
             else
-                shader_addline(buffer, "gl_FogFragCoord = abs(ec_pos.z);\n");
+                shader_addline(buffer, "ffp_varying_fogcoord = abs(ec_pos.z);\n");
             break;
 
         default:
             ERR("Unhandled fog mode %#x.\n", settings->fog_mode);
             break;
     }
+    if (output_legacy_fogcoord)
+        shader_addline(buffer, "gl_FogFragCoord = ffp_varying_fogcoord;\n");
 
     if (settings->point_size)
     {
@@ -5812,12 +6031,12 @@ static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buf
     switch (arg & WINED3DTA_SELECTMASK)
     {
         case WINED3DTA_DIFFUSE:
-            ret = "gl_Color";
+            ret = "ffp_varying_diffuse";
             break;
 
         case WINED3DTA_CURRENT:
             if (!stage)
-                ret = "gl_Color";
+                ret = "ffp_varying_diffuse";
             else
                 ret = "ret";
             break;
@@ -5844,7 +6063,7 @@ static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buf
             break;
 
         case WINED3DTA_SPECULAR:
-            ret = "gl_SecondaryColor";
+            ret = "ffp_varying_specular";
             break;
 
         case WINED3DTA_TEMP:
@@ -5922,7 +6141,7 @@ static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, un
     {
         case WINED3D_TOP_DISABLE:
             if (!stage)
-                shader_addline(buffer, "%s%s = gl_Color%s;\n", dstreg, dstmask, dstmask);
+                shader_addline(buffer, "%s%s = ffp_varying_diffuse%s;\n", dstreg, dstmask, dstmask);
             break;
 
         case WINED3D_TOP_SELECT_ARG1:
@@ -6061,6 +6280,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
     DWORD arg0, arg1, arg2;
     unsigned int stage;
     struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers);
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
 
     string_buffer_clear(buffer);
 
@@ -6076,7 +6296,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
 
         if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE
                 || (stage == 0 && settings->color_key_enabled))
-            tex_map |= 1 << stage;
+            tex_map |= 1u << stage;
         if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
             tfactor_used = TRUE;
         if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
@@ -6084,19 +6304,19 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         if (settings->op[stage].dst == tempreg)
             tempreg_used = TRUE;
         if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
-            tss_const_map |= 1 << stage;
+            tss_const_map |= 1u << stage;
 
         switch (settings->op[stage].cop)
         {
             case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
-                lum_map |= 1 << stage;
+                lum_map |= 1u << stage;
                 /* fall through */
             case WINED3D_TOP_BUMPENVMAP:
-                bump_map |= 1 << stage;
+                bump_map |= 1u << stage;
                 /* fall through */
             case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
             case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
-                tex_map |= 1 << stage;
+                tex_map |= 1u << stage;
                 break;
 
             case WINED3D_TOP_BLEND_FACTOR_ALPHA:
@@ -6115,13 +6335,13 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK;
 
         if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE)
-            tex_map |= 1 << stage;
+            tex_map |= 1u << stage;
         if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
             tfactor_used = TRUE;
         if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
             tempreg_used = TRUE;
         if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
-            tss_const_map |= 1 << stage;
+            tss_const_map |= 1u << stage;
     }
     lowest_disabled_stage = stage;
 
@@ -6138,10 +6358,10 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
 
     for (stage = 0; stage < MAX_TEXTURES; ++stage)
     {
-        if (tss_const_map & (1 << stage))
+        if (tss_const_map & (1u << stage))
             shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage);
 
-        if (!(tex_map & (1 << stage)))
+        if (!(tex_map & (1u << stage)))
             continue;
 
         switch (settings->op[stage].tex_type)
@@ -6168,11 +6388,11 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
 
         shader_addline(buffer, "vec4 tex%u;\n", stage);
 
-        if (!(bump_map & (1 << stage)))
+        if (!(bump_map & (1u << stage)))
             continue;
         shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", stage);
 
-        if (!(lum_map & (1 << stage)))
+        if (!(lum_map & (1u << stage)))
             continue;
         shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", stage);
         shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", stage);
@@ -6180,7 +6400,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
     if (tfactor_used)
         shader_addline(buffer, "uniform vec4 tex_factor;\n");
     if (settings->color_key_enabled)
-        shader_addline(buffer, "uniform vec4 color_key;\n");
+        shader_addline(buffer, "uniform vec4 color_key[2];\n");
     shader_addline(buffer, "uniform vec4 specular_enable;\n");
 
     if (settings->sRGB_write)
@@ -6200,10 +6420,50 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
     shader_addline(buffer, "    float scale;\n");
     shader_addline(buffer, "} ffp_fog;\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, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES);
+        shader_addline(buffer, "float ffp_varying_fogcoord;\n");
+    }
+    else
+    {
+        declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n");
+        declare_in_varying(gl_info, buffer, settings->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");
+    }
+
     shader_addline(buffer, "void main()\n{\n");
 
+    if (legacy_context)
+    {
+        shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n");
+        shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n");
+    }
+
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (tex_map & (1u << stage))
+        {
+            if (settings->pointsprite)
+                shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", stage);
+            else if (settings->texcoords_initialized & (1u << stage))
+                shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n",
+                        stage, legacy_context ? "gl_TexCoord" : "ffp_varying_texcoord", stage);
+            else
+                shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", stage);
+        }
+    }
+
+    if (legacy_context && settings->fog != WINED3D_FFP_PS_FOG_OFF)
+        shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n");
+
     if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
-        shader_addline(buffer, "if (any(lessThan(gl_TexCoord[7], vec4(0.0)))) discard;\n");
+        shader_addline(buffer, "if (any(lessThan(ffp_texcoord[7], vec4(0.0)))) discard;\n");
 
     /* Generate texture sampling instructions) */
     for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage)
@@ -6211,7 +6471,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         const char *texture_function, *coord_mask;
         BOOL proj;
 
-        if (!(tex_map & (1 << stage)))
+        if (!(tex_map & (1u << stage)))
             continue;
 
         if (settings->op[stage].projected == proj_none)
@@ -6229,6 +6489,9 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
             proj = TRUE;
         }
 
+        if (settings->op[stage].tex_type == WINED3D_GL_RES_TYPE_TEX_CUBE)
+            proj = FALSE;
+
         switch (settings->op[stage].tex_type)
         {
             case WINED3D_GL_RES_TYPE_TEX_1D:
@@ -6289,6 +6552,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
                 coord_mask = "xyzw";
                 break;
         }
+        if (!needs_legacy_glsl_syntax(gl_info))
+            texture_function = proj ? "textureProj" : "texture";
 
         if (stage > 0
                 && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
@@ -6304,20 +6569,20 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
             {
                 if (settings->op[stage].projected == proj_count4)
                 {
-                    shader_addline(buffer, "ret.xy = (ret.xy * gl_TexCoord[%u].w) + gl_TexCoord[%u].xy;\n",
+                    shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n",
                             stage, stage);
-                    shader_addline(buffer, "ret.zw = gl_TexCoord[%u].ww;\n", stage);
+                    shader_addline(buffer, "ret.zw = ffp_texcoord[%u].ww;\n", stage);
                 }
                 else
                 {
-                    shader_addline(buffer, "ret.xy = (ret.xy * gl_TexCoord[%u].z) + gl_TexCoord[%u].xy;\n",
+                    shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].z) + ffp_texcoord[%u].xy;\n",
                             stage, stage);
-                    shader_addline(buffer, "ret.zw = gl_TexCoord[%u].zz;\n", stage);
+                    shader_addline(buffer, "ret.zw = ffp_texcoord[%u].zz;\n", stage);
                 }
             }
             else
             {
-                shader_addline(buffer, "ret = gl_TexCoord[%u] + ret.xyxy;\n", stage);
+                shader_addline(buffer, "ret = ffp_texcoord[%u] + ret.xyxy;\n", stage);
             }
 
             shader_addline(buffer, "tex%u = %s(ps_sampler%u, ret.%s);\n",
@@ -6329,12 +6594,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         }
         else if (settings->op[stage].projected == proj_count3)
         {
-            shader_addline(buffer, "tex%u = %s(ps_sampler%u, gl_TexCoord[%u].xyz);\n",
+            shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n",
                     stage, texture_function, stage, stage);
         }
         else
         {
-            shader_addline(buffer, "tex%u = %s(ps_sampler%u, gl_TexCoord[%u].%s);\n",
+            shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].%s);\n",
                     stage, texture_function, stage, stage, coord_mask);
         }
 
@@ -6344,7 +6609,10 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
     }
 
     if (settings->color_key_enabled)
-        shader_addline(buffer, "if (all(equal(tex0, color_key))) discard;\n");
+    {
+        shader_addline(buffer, "if (all(greaterThanEqual(tex0, color_key[0])) && all(lessThan(tex0, color_key[1])))\n");
+        shader_addline(buffer, "    discard;\n");
+    }
 
     /* Generate the main shader */
     for (stage = 0; stage < MAX_TEXTURES; ++stage)
@@ -6354,7 +6622,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
         {
             if (!stage)
-                final_combiner_src = "gl_Color";
+                final_combiner_src = "ffp_varying_diffuse";
             break;
         }
 
@@ -6382,7 +6650,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
                     settings->op[stage].cop, settings->op[stage].carg0,
                     settings->op[stage].carg1, settings->op[stage].carg2);
             if (!stage)
-                shader_addline(buffer, "ret.w = gl_Color.w;\n");
+                shader_addline(buffer, "ret.w = ffp_varying_diffuse.w;\n");
         }
         else if (op_equal)
         {
@@ -6401,7 +6669,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         }
     }
 
-    shader_addline(buffer, "gl_FragData[0] = gl_SecondaryColor * specular_enable + %s;\n", final_combiner_src);
+    shader_addline(buffer, "gl_FragData[0] = ffp_varying_specular * specular_enable + %s;\n", final_combiner_src);
 
     if (settings->sRGB_write)
         shader_glsl_generate_srgb_write_correction(buffer);
@@ -6430,7 +6698,7 @@ static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct
         return NULL;
 
     shader->desc.settings = *settings;
-    shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info, priv->legacy_lighting);
+    shader->id = shader_glsl_generate_ffp_vertex_shader(priv, settings, gl_info);
     list_init(&shader->linked_programs);
     if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1)
         ERR("Failed to insert ffp vertex shader.\n");
@@ -6626,6 +6894,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
         struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     const struct ps_np2fixup_info *np2fixup_info = NULL;
     struct glsl_shader_prog_link *entry = NULL;
     struct wined3d_shader *vshader = NULL;
@@ -6641,7 +6910,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     WORD attribs_map;
     struct wined3d_string_buffer *tmp_name;
 
-    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_VERTEX)) && ctx_data->glsl_program)
+    if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_VERTEX)) && ctx_data->glsl_program)
     {
         vs_id = ctx_data->glsl_program->vs.id;
         vs_list = &ctx_data->glsl_program->vs.shader_entry;
@@ -6651,7 +6920,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
             vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
             gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
 
-            if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_GEOMETRY))
+            if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY))
                     && ctx_data->glsl_program->gs.id)
                 gs_id = ctx_data->glsl_program->gs.id;
             else if (gshader)
@@ -6661,9 +6930,10 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     else if (use_vs(state))
     {
         struct vs_compile_args vs_compile_args;
+
         vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
 
-        find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args);
+        find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, d3d_info);
         vs_id = find_glsl_vshader(context, &priv->shader_buffer, &priv->string_buffers, vshader, &vs_compile_args);
         vs_list = &vshader->linked_programs;
 
@@ -6675,13 +6945,13 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
         struct glsl_ffp_vertex_shader *ffp_shader;
         struct wined3d_ffp_vs_settings settings;
 
-        wined3d_ffp_get_vs_settings(state, &context->stream_info, &settings);
+        wined3d_ffp_get_vs_settings(context, state, &settings);
         ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings);
         vs_id = ffp_shader->id;
         vs_list = &ffp_shader->linked_programs;
     }
 
-    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_PIXEL)) && ctx_data->glsl_program)
+    if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_PIXEL)) && ctx_data->glsl_program)
     {
         ps_id = ctx_data->glsl_program->ps.id;
         ps_list = &ctx_data->glsl_program->ps.shader_entry;
@@ -6693,7 +6963,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     {
         struct ps_compile_args ps_compile_args;
         pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
-        find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, gl_info);
+        find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, context);
         ps_id = find_glsl_pshader(context, &priv->shader_buffer, &priv->string_buffers,
                 pshader, &ps_compile_args, &np2fixup_info);
         ps_list = &pshader->linked_programs;
@@ -6747,7 +7017,9 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     {
         attribs_map = vshader->reg_maps.input_registers;
         reorder_shader_id = generate_param_reorder_function(priv, vshader, pshader,
-                state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size, gl_info);
+                state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size,
+                d3d_info->emulated_flatshading
+                && state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT, gl_info);
         TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id);
         GL_EXTCALL(glAttachShader(program_id, reorder_shader_id));
         checkGLcall("glAttachShader");
@@ -6758,7 +7030,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     }
     else
     {
-        attribs_map = (1 << WINED3D_FFP_ATTRIBS_COUNT) - 1;
+        attribs_map = (1u << WINED3D_FFP_ATTRIBS_COUNT) - 1;
     }
 
     /* Bind vertex attributes to a corresponding index number to match
@@ -6839,13 +7111,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     GL_EXTCALL(glUseProgram(program_id));
     checkGLcall("glUseProgram");
 
-    /* Load the vertex and pixel samplers now. The function that finds the mappings makes sure
-     * that it stays the same for each vertexshader-pixelshader pair(=linked glsl program). If
-     * a pshader with fixed function pipeline is used there are no vertex samplers, and if a
-     * vertex shader with fixed function pixel processing is used we make sure that the card
-     * supports enough samplers to allow the max number of vertex samplers with all possible
-     * fixed function fragment processing setups. So once the program is linked these samplers
-     * won't change. */
+    /* Texture unit mapping is set up to be the same each time the shader
+     * program is used so we can hardcode the sampler uniform values. */
     shader_glsl_load_samplers(gl_info, priv, context->tex_unit_map, program_id);
 
     entry->constant_update_mask = 0;
@@ -7124,9 +7391,9 @@ static void shader_glsl_invalidate_current_program(struct wined3d_context *conte
     struct glsl_context_data *ctx_data = context->shader_backend_data;
 
     ctx_data->glsl_program = NULL;
-    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
-            | (1 << WINED3D_SHADER_TYPE_VERTEX)
-            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+    context->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. */
@@ -7505,10 +7772,8 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s
 {
     UINT shader_model;
 
-    if (gl_info->supported[EXT_GPU_SHADER4] && gl_info->supported[ARB_SHADER_BIT_ENCODING]
-            && gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)
-            && gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && gl_info->supported[ARB_DRAW_INSTANCED]
-            && gl_info->supported[ARB_TEXTURE_RG] && gl_info->supported[ARB_SAMPLER_OBJECTS])
+    if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50) && gl_info->supported[WINED3D_GL_VERSION_3_2]
+            && gl_info->supported[ARB_SHADER_BIT_ENCODING] && gl_info->supported[ARB_SAMPLER_OBJECTS])
         shader_model = 4;
     /* ARB_shader_texture_lod or EXT_gpu_shader4 is required for the SM3
      * texldd and texldl instructions. */
@@ -7524,6 +7789,7 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s
 
     caps->vs_uniform_count = gl_info->limits.glsl_vs_float_constants;
     caps->ps_uniform_count = gl_info->limits.glsl_ps_float_constants;
+    caps->varying_count = gl_info->limits.glsl_varyings;
 
     /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
      * Direct3D minimum requirement.
@@ -7738,6 +8004,7 @@ static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BO
 static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
 {
     caps->xyzrhw = TRUE;
+    caps->emulated_flatshading = !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
     caps->ffp_generic_attributes = TRUE;
     caps->max_active_lights = MAX_ACTIVE_LIGHTS;
     caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS;
@@ -7754,6 +8021,13 @@ static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info,
     caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE;
 }
 
+static DWORD glsl_vertex_pipe_vp_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+        return GL_EXT_EMUL_ARB_MULTITEXTURE;
+    return 0;
+}
+
 static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
 {
     struct shader_glsl_priv *priv;
@@ -7803,10 +8077,13 @@ static void glsl_vertex_pipe_vp_free(struct wined3d_device *device)
     wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx);
 }
 
+static void glsl_vertex_pipe_nop(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) {}
+
 static void glsl_vertex_pipe_shader(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
 }
 
 static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
@@ -7823,7 +8100,7 @@ static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
      * the draw uses the fixed function vertex pipeline regardless of any
      * vertex shader set by the application. */
     if (transformed != wasrhw)
-        context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
 
     if (!use_vs(state))
     {
@@ -7835,16 +8112,16 @@ static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
 
         context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
 
-        /* Because of settings->texcoords, we have to always regenerate the
-         * vertex shader on a vdecl change.
-         * TODO: Just always output all the texcoords when there are enough
-         * varyings available to drop the dependency. */
-        context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+        /* Because of settings->texcoords, we have to regenerate the vertex
+         * shader on a vdecl change if there aren't enough varyings to just
+         * always output all the texture coordinates. */
+        if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info))
+            context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
 
         if (use_ps(state)
                 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1
                 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3)
-            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+            context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
     }
     else
     {
@@ -7862,7 +8139,7 @@ static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
 static void glsl_vertex_pipe_vs(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
     /* Different vertex shaders potentially require a different vertex attributes setup. */
     if (!isStateDirty(context, STATE_VDECL))
         context_apply_state(context, state, STATE_VDECL);
@@ -7902,7 +8179,7 @@ static void glsl_vertex_pipe_projection(struct wined3d_context *context,
     /* Table fog behavior depends on the projection matrix. */
     if (state->render_states[WINED3D_RS_FOGENABLE]
             && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
-        context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
     context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PROJ;
 }
 
@@ -7937,12 +8214,12 @@ static void glsl_vertex_pipe_texmatrix_np2(struct wined3d_context *context,
         return;
 
     if ((np2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
-            || context->lastWasPow2Texture & (1 << sampler))
+            || context->lastWasPow2Texture & (1u << sampler))
     {
         if (np2)
-            context->lastWasPow2Texture |= 1 << sampler;
+            context->lastWasPow2Texture |= 1u << sampler;
         else
-            context->lastWasPow2Texture &= ~(1 << sampler);
+            context->lastWasPow2Texture &= ~(1u << sampler);
 
         context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
     }
@@ -7973,6 +8250,12 @@ static void glsl_vertex_pipe_pointscale(struct wined3d_context *context,
         context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE;
 }
 
+static void glsl_vertex_pipe_shademode(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+}
+
 static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
 {
     {STATE_VDECL,                                                {STATE_VDECL,                                                glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE          },
@@ -8112,27 +8395,18 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
     {STATE_SAMPLER(7),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
     {STATE_SAMPLER(7),                                           {STATE_SAMPLER(7),                                           glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE   },
     {STATE_POINT_ENABLE,                                         {STATE_POINT_ENABLE,                                         glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                         {STATE_RENDER(WINED3D_RS_SHADEMODE),                         glsl_vertex_pipe_nop   },  WINED3D_GL_LEGACY_CONTEXT   },
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                         {STATE_RENDER(WINED3D_RS_SHADEMODE),                         glsl_vertex_pipe_shademode}, WINED3D_GL_EXT_NONE       },
     {0 /* Terminate */,                                          {0,                                                          NULL                   }, WINED3D_GL_EXT_NONE          },
 };
 
 /* TODO:
- *   - This currently depends on GL fixed function functions to set things
- *     like light parameters. Ideally we'd use regular uniforms for that.
- *   - In part because of the previous point, much of this is modelled after
- *     GL fixed function, and has much of the same limitations. For example,
- *     D3D spot lights are slightly different from GL spot lights.
- *   - We can now implement drawing transformed vertices using the GLSL pipe,
- *     instead of using the immediate mode fallback.
- *   - Similarly, we don't need the fallback for certain combinations of
- *     material sources anymore.
- *   - Implement vertex tweening.
- *   - Handle WINED3D_TSS_TEXCOORD_INDEX in the shader, instead of duplicating
- *     attribute arrays in load_tex_coords().
- *   - Per-vertex point sizes. */
+ *   - Implement vertex tweening. */
 const struct wined3d_vertex_pipe_ops glsl_vertex_pipe =
 {
     glsl_vertex_pipe_vp_enable,
     glsl_vertex_pipe_vp_get_caps,
+    glsl_vertex_pipe_vp_get_emul_mask,
     glsl_vertex_pipe_vp_alloc,
     glsl_vertex_pipe_vp_free,
     glsl_vertex_pipe_vp_states,
@@ -8179,6 +8453,13 @@ static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, s
     caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8);
 }
 
+static DWORD glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+        return GL_EXT_EMUL_ARB_MULTITEXTURE;
+    return 0;
+}
+
 static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
 {
     struct shader_glsl_priv *priv;
@@ -8233,7 +8514,7 @@ static void glsl_fragment_pipe_shader(struct wined3d_context *context,
 {
     context->last_was_pshader = use_ps(state);
 
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_fogparams(struct wined3d_context *context,
@@ -8250,7 +8531,7 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
     DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
     DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
 
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
 
     if (!state->render_states[WINED3D_RS_FOGENABLE])
         return;
@@ -8279,14 +8560,26 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
 static void glsl_fragment_pipe_vdecl(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
+    /* Because of settings->texcoords_initialized and args->texcoords_initialized. */
+    if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+
     if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE)))
         glsl_fragment_pipe_fog(context, state, state_id);
 }
 
+static void glsl_fragment_pipe_vs(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    /* Because of settings->texcoords_initialized and args->texcoords_initialized. */
+    if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info))
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+}
+
 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context,
@@ -8332,9 +8625,16 @@ static void glsl_fragment_pipe_color_key(struct wined3d_context *context,
     context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY;
 }
 
+static void glsl_fragment_pipe_shademode(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+}
+
 static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
 {
     {STATE_VDECL,                                               {STATE_VDECL,                                                glsl_fragment_pipe_vdecl               }, WINED3D_GL_EXT_NONE },
+    {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX),                  {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX),                   glsl_fragment_pipe_vs                  }, WINED3D_GL_EXT_NONE },
     {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),                    {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),                     glsl_fragment_pipe_invalidate_constants}, 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 },
@@ -8442,6 +8742,8 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT),               {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT),                glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
     {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                   {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
     {STATE_POINT_ENABLE,                                        {STATE_POINT_ENABLE,                                         glsl_fragment_pipe_shader              }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                        {STATE_RENDER(WINED3D_RS_SHADEMODE),                         state_shademode                        }, WINED3D_GL_LEGACY_CONTEXT},
+    {STATE_RENDER(WINED3D_RS_SHADEMODE),                        {STATE_RENDER(WINED3D_RS_SHADEMODE),                         glsl_fragment_pipe_shademode           }, WINED3D_GL_EXT_NONE },
     {0 /* Terminate */,                                         {0,                                                          0                                      }, WINED3D_GL_EXT_NONE },
 };
 
@@ -8458,6 +8760,7 @@ const struct fragment_pipeline glsl_fragment_pipe =
 {
     glsl_fragment_pipe_enable,
     glsl_fragment_pipe_get_caps,
+    glsl_fragment_pipe_get_emul_mask,
     glsl_fragment_pipe_alloc,
     glsl_fragment_pipe_free,
     glsl_fragment_pipe_alloc_context_data,
index 1b85b65..51fc9bc 100644 (file)
@@ -36,9 +36,11 @@ static void nvts_activate_dimensions(const struct wined3d_state *state, DWORD st
             || state->texture_states[stage - 1][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP))
     {
         bumpmap = TRUE;
-        context->texShaderBumpMap |= (1 << stage);
-    } else {
-        context->texShaderBumpMap &= ~(1 << stage);
+        context->texShaderBumpMap |= (1u << stage);
+    }
+    else
+    {
+        context->texShaderBumpMap &= ~(1u << stage);
     }
 
     if (state->textures[stage])
@@ -472,7 +474,7 @@ void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d
 static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
     DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -565,7 +567,7 @@ static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_s
     {
         BOOL usesBump = (state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP_LUMINANCE
                 || state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP);
-        BOOL usedBump = !!(context->texShaderBumpMap & 1 << (stage + 1));
+        BOOL usedBump = !!(context->texShaderBumpMap & 1u << (stage + 1));
         if (usesBump != usedBump)
         {
             context_active_texture(context, gl_info, mapped_stage + 1);
@@ -733,6 +735,11 @@ static void nvrc_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct
     caps->MaxSimultaneousTextures = gl_info->limits.textures;
 }
 
+static DWORD nvrc_fragment_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
+}
+
 static void *nvrc_fragment_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
 {
     return shader_priv;
@@ -887,6 +894,7 @@ static const struct StateEntryTemplate nvrc_fragmentstate_template[] =
     { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_FOGSTART),                  { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend   }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_FOGEND),                    { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SHADEMODE),                 { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode     }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
@@ -919,6 +927,7 @@ static void nvrc_context_free(struct wined3d_context *context)
 const struct fragment_pipeline nvts_fragment_pipeline = {
     nvts_enable,
     nvrc_fragment_get_caps,
+    nvrc_fragment_get_emul_mask,
     nvrc_fragment_alloc,
     nvrc_fragment_free,
     nvrc_context_alloc,
@@ -930,6 +939,7 @@ const struct fragment_pipeline nvts_fragment_pipeline = {
 const struct fragment_pipeline nvrc_fragment_pipeline = {
     nvrc_enable,
     nvrc_fragment_get_caps,
+    nvrc_fragment_get_emul_mask,
     nvrc_fragment_alloc,
     nvrc_fragment_free,
     nvrc_context_alloc,
index 15599da..7fcc126 100644 (file)
@@ -151,8 +151,8 @@ HRESULT CDECL wined3d_palette_create(struct wined3d_device *device, DWORD flags,
     struct wined3d_palette *object;
     HRESULT hr;
 
-    TRACE("device %p, flags %#x, entries %p, palette %p.\n",
-            device, flags, entries, palette);
+    TRACE("device %p, flags %#x, entry_count %u, entries %p, palette %p.\n",
+            device, flags, entry_count, entries, palette);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
index 51447e0..bc95a7d 100644 (file)
@@ -112,7 +112,7 @@ enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_
     const struct wined3d_gl_info *gl_info;
     enum wined3d_event_query_result ret;
 
-    TRACE("(%p)\n", query);
+    TRACE("query %p, device %p.\n", query, device);
 
     if (!query->context)
     {
@@ -938,6 +938,14 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer
         void *data, DWORD size, DWORD flags)
 {
     TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
+    if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT)
+    {
+        static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {1000 * 1000 * 1000, FALSE};
+
+        if (query->state == QUERY_BUILDING)
+        {
+             TRACE("Query is building, returning S_FALSE.\n");
+             return S_FALSE;
 #else  /* STAGING_CSMT */
         query->state = QUERY_SIGNALLED;
 
@@ -949,7 +957,6 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer
 {
     TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
 
-#endif /* STAGING_CSMT */
     if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT)
     {
         static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {1000 * 1000 * 1000, FALSE};
@@ -958,6 +965,7 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer
         {
             TRACE("Query is building, returning S_FALSE.\n");
             return S_FALSE;
+#endif /* STAGING_CSMT */
         }
 
         fill_query_data(data, size, &disjoint_data, sizeof(disjoint_data));
@@ -1166,7 +1174,7 @@ HRESULT CDECL wined3d_query_create(struct wined3d_device *device,
     struct wined3d_query *object;
     HRESULT hr;
 
-    TRACE("device %p, type %#x, query %p.\n", device, type, query);
+    TRACE("device %p, type %#x, parent %p, query %p.\n", device, type, parent, query);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
index 4478eba..f9008c2 100644 (file)
@@ -335,6 +335,22 @@ void CDECL wined3d_resource_get_desc(const struct wined3d_resource *resource, st
     desc->size = resource->size;
 }
 
+HRESULT CDECL wined3d_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)
+{
+    TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %p, flags %#x.\n",
+            resource, sub_resource_idx, map_desc, box, flags);
+
+    return resource->resource_ops->resource_sub_resource_map(resource, sub_resource_idx, map_desc, box, flags);
+}
+
+HRESULT CDECL wined3d_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx);
+
+    return resource->resource_ops->resource_sub_resource_unmap(resource, sub_resource_idx);
+}
+
 BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource)
 {
     void **p;
@@ -462,8 +478,9 @@ void wined3d_resource_update_draw_binding(struct wined3d_resource *resource)
     else
         resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB;
 }
+#if defined(STAGING_CSMT)
 
-void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch,
+void wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch,
         UINT *slice_pitch)
 {
     unsigned int alignment;
@@ -493,7 +510,6 @@ void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, U
 
     TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch);
 }
-#if defined(STAGING_CSMT)
 
 void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location)
 {
@@ -876,7 +892,7 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource,
     struct wined3d_device *device = resource->device;
     BYTE *base_memory;
     const struct wined3d_format *format = resource->format;
-    const unsigned int fmt_flags = resource->format_flags;
+    const unsigned int fmt_flags = resource->format->flags[WINED3D_GL_RES_TYPE_TEX_2D];
 
     TRACE("resource %p, map_desc %p, box %p, flags %#x.\n",
             resource, map_desc, box, flags);
index 84ba74a..1f5151b 100644 (file)
@@ -30,6 +30,29 @@ ULONG CDECL wined3d_sampler_incref(struct wined3d_sampler *sampler)
     return refcount;
 }
 
+#if defined(STAGING_CSMT)
+void wined3d_sampler_destroy(struct wined3d_sampler *sampler)
+{
+    struct wined3d_context *context = context_acquire(sampler->device, NULL);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glDeleteSamplers(1, &sampler->name));
+    context_release(context);
+
+    HeapFree(GetProcessHeap(), 0, sampler);
+}
+
+ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
+{
+    ULONG refcount = InterlockedDecrement(&sampler->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", sampler, refcount);
+
+    if (!refcount)
+    {
+        struct wined3d_device *device = sampler->device;
+        wined3d_cs_emit_sampler_destroy(device->cs, sampler);
+#else  /* STAGING_CSMT */
 ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
 {
     ULONG refcount = InterlockedDecrement(&sampler->refcount);
@@ -46,6 +69,7 @@ ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
         context_release(context);
 
         HeapFree(GetProcessHeap(), 0, sampler);
+#endif /* STAGING_CSMT */
     }
 
     return refcount;
index c05e61d..8d2d28a 100644 (file)
@@ -492,7 +492,7 @@ static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit)
     DWORD idx, shift;
     idx = bit >> 5;
     shift = bit & 0x1f;
-    bitmap[idx] |= (1 << shift);
+    bitmap[idx] |= (1u << shift);
 }
 
 static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct wined3d_shader_reg_maps *reg_maps,
@@ -502,13 +502,13 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w
     {
         case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
             if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
-                reg_maps->texcoord |= 1 << reg->idx[0].offset;
+                reg_maps->texcoord |= 1u << reg->idx[0].offset;
             else
-                reg_maps->address |= 1 << reg->idx[0].offset;
+                reg_maps->address |= 1u << reg->idx[0].offset;
             break;
 
         case WINED3DSPR_TEMP:
-            reg_maps->temporary |= 1 << reg->idx[0].offset;
+            reg_maps->temporary |= 1u << reg->idx[0].offset;
             break;
 
         case WINED3DSPR_INPUT:
@@ -531,7 +531,7 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w
                 }
             }
             else
-                reg_maps->input_registers |= 1 << reg->idx[0].offset;
+                reg_maps->input_registers |= 1u << reg->idx[0].offset;
             break;
 
         case WINED3DSPR_RASTOUT:
@@ -582,7 +582,7 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w
             }
             else
             {
-                reg_maps->integer_constants |= (1 << reg->idx[0].offset);
+                reg_maps->integer_constants |= (1u << reg->idx[0].offset);
             }
             break;
 
@@ -594,12 +594,12 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w
             }
             else
             {
-                reg_maps->boolean_constants |= (1 << reg->idx[0].offset);
+                reg_maps->boolean_constants |= (1u << reg->idx[0].offset);
             }
             break;
 
         case WINED3DSPR_COLOROUT:
-            reg_maps->rt_mask |= (1 << reg->idx[0].offset);
+            reg_maps->rt_mask |= (1u << reg->idx[0].offset);
             break;
 
         default:
@@ -738,7 +738,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                     if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL && shader_version.major == 3
                             && semantic->usage == WINED3D_DECL_USAGE_POSITION && !semantic->usage_idx)
                         return WINED3DERR_INVALIDCALL;
-                    reg_maps->input_registers |= 1 << reg_idx;
+                    reg_maps->input_registers |= 1u << reg_idx;
                     shader_signature_from_semantic(&input_signature_elements[reg_idx], semantic);
                     break;
 
@@ -749,7 +749,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                         ERR("Invalid output register index %u.\n", reg_idx);
                         break;
                     }
-                    reg_maps->output_registers |= 1 << reg_idx;
+                    reg_maps->output_registers |= 1u << reg_idx;
                     shader_signature_from_semantic(&output_signature_elements[reg_idx], semantic);
                     if (semantic->usage == WINED3D_DECL_USAGE_FOG)
                         reg_maps->fog = 1;
@@ -846,7 +846,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
             memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
 
             list_add_head(&shader->constantsI, &lconst->entry);
-            reg_maps->local_int_consts |= (1 << lconst->idx);
+            reg_maps->local_int_consts |= (1u << lconst->idx);
         }
         else if (ins.handler_idx == WINED3DSIH_DEFB)
         {
@@ -857,12 +857,12 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
             memcpy(lconst->value, ins.src[0].reg.immconst_data, sizeof(DWORD));
 
             list_add_head(&shader->constantsB, &lconst->entry);
-            reg_maps->local_bool_consts |= (1 << lconst->idx);
+            reg_maps->local_bool_consts |= (1u << lconst->idx);
         }
         /* For subroutine prototypes. */
         else if (ins.handler_idx == WINED3DSIH_LABEL)
         {
-            reg_maps->labels |= 1 << ins.src[0].reg.idx[0].offset;
+            reg_maps->labels |= 1u << ins.src[0].reg.idx[0].offset;
         }
         /* Set texture, address, temporary registers. */
         else
@@ -882,32 +882,31 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                         shader_version.type, constf_size))
                     return WINED3DERR_INVALIDCALL;
 
-                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
-                 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
-                 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
-                if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3)
+                if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX)
                 {
                     UINT idx = ins.dst[i].reg.idx[0].offset;
 
                     switch (ins.dst[i].reg.type)
                     {
                         case WINED3DSPR_RASTOUT:
+                            if (shader_version.major >= 3)
+                                break;
                             switch (idx)
                             {
                                 case 0: /* oPos */
-                                    reg_maps->output_registers |= 1 << 10;
+                                    reg_maps->output_registers |= 1u << 10;
                                     shader_signature_from_usage(&output_signature_elements[10],
                                             WINED3D_DECL_USAGE_POSITION, 0, 10, WINED3DSP_WRITEMASK_ALL);
                                     break;
 
                                 case 1: /* oFog */
-                                    reg_maps->output_registers |= 1 << 11;
+                                    reg_maps->output_registers |= 1u << 11;
                                     shader_signature_from_usage(&output_signature_elements[11],
                                             WINED3D_DECL_USAGE_FOG, 0, 11, WINED3DSP_WRITEMASK_0);
                                     break;
 
                                 case 2: /* oPts */
-                                    reg_maps->output_registers |= 1 << 11;
+                                    reg_maps->output_registers |= 1u << 11;
                                     shader_signature_from_usage(&output_signature_elements[11],
                                             WINED3D_DECL_USAGE_PSIZE, 0, 11, WINED3DSP_WRITEMASK_1);
                                     break;
@@ -915,16 +914,18 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                             break;
 
                         case WINED3DSPR_ATTROUT:
+                            if (shader_version.major >= 3)
+                                break;
                             if (idx < 2)
                             {
                                 idx += 8;
-                                if (reg_maps->output_registers & (1 << idx))
+                                if (reg_maps->output_registers & (1u << idx))
                                 {
                                     output_signature_elements[idx].mask |= ins.dst[i].write_mask;
                                 }
                                 else
                                 {
-                                    reg_maps->output_registers |= 1 << idx;
+                                    reg_maps->output_registers |= 1u << idx;
                                     shader_signature_from_usage(&output_signature_elements[idx],
                                             WINED3D_DECL_USAGE_COLOR, idx - 8, idx, ins.dst[i].write_mask);
                                 }
@@ -932,15 +933,19 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                             break;
 
                         case WINED3DSPR_TEXCRDOUT:
-
-                            reg_maps->texcoord_mask[idx] |= ins.dst[i].write_mask;
-                            if (reg_maps->output_registers & (1 << idx))
+                            if (shader_version.major >= 3)
+                            {
+                                reg_maps->u.output_registers_mask[idx] |= ins.dst[i].write_mask;
+                                break;
+                            }
+                            reg_maps->u.texcoord_mask[idx] |= ins.dst[i].write_mask;
+                            if (reg_maps->output_registers & (1u << idx))
                             {
                                 output_signature_elements[idx].mask |= ins.dst[i].write_mask;
                             }
                             else
                             {
-                                reg_maps->output_registers |= 1 << idx;
+                                reg_maps->output_registers |= 1u << idx;
                                 shader_signature_from_usage(&output_signature_elements[idx],
                                         WINED3D_DECL_USAGE_TEXCOORD, idx, idx, ins.dst[i].write_mask);
                             }
@@ -1005,16 +1010,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                     if (ins.handler_idx == WINED3DSIH_TEXBEM
                             || ins.handler_idx == WINED3DSIH_TEXBEML)
                     {
-                        reg_maps->bumpmat |= 1 << reg_idx;
+                        reg_maps->bumpmat |= 1u << reg_idx;
                         if (ins.handler_idx == WINED3DSIH_TEXBEML)
                         {
-                            reg_maps->luminanceparams |= 1 << reg_idx;
+                            reg_maps->luminanceparams |= 1u << reg_idx;
                         }
                     }
                 }
                 else if (ins.handler_idx == WINED3DSIH_BEM)
                 {
-                    reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx[0].offset;
+                    reg_maps->bumpmat |= 1u << ins.dst[i].reg.idx[0].offset;
                 }
             }
 
@@ -1086,7 +1091,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     /* PS before 2.0 don't have explicit color outputs. Instead the value of
      * R0 is written to the render target. */
     if (shader_version.major < 2 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
-        reg_maps->rt_mask |= (1 << 0);
+        reg_maps->rt_mask |= (1u << 0);
 
     shader->functionLength = ((const char *)ptr - (const char *)byte_code);
 
@@ -1094,7 +1099,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     {
         for (i = 0; i < input_signature->element_count; ++i)
         {
-            reg_maps->input_registers |= 1 << input_signature->elements[i].register_idx;
+            reg_maps->input_registers |= 1u << input_signature->elements[i].register_idx;
             if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL
                     && input_signature->elements[i].sysval_semantic == WINED3D_SV_POSITION)
                 reg_maps->vpos = 1;
@@ -1113,7 +1118,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
         e = input_signature->elements;
         for (i = 0; i < ARRAY_SIZE(input_signature_elements); ++i)
         {
-            if (!(reg_maps->input_registers & (1 << i)))
+            if (!(reg_maps->input_registers & (1u << i)))
                 continue;
             input_signature_elements[i].register_idx = i;
             *e++ = input_signature_elements[i];
@@ -1124,7 +1129,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     {
         for (i = 0; i < output_signature->element_count; ++i)
         {
-            reg_maps->output_registers |= 1 << output_signature->elements[i].register_idx;
+            reg_maps->output_registers |= 1u << output_signature->elements[i].register_idx;
         }
     }
     else if (reg_maps->output_registers)
@@ -1139,7 +1144,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
         e = output_signature->elements;
         for (i = 0; i < ARRAY_SIZE(output_signature_elements); ++i)
         {
-            if (!(reg_maps->output_registers & (1 << i)))
+            if (!(reg_maps->output_registers & (1u << i)))
                 continue;
             *e++ = output_signature_elements[i];
         }
@@ -1150,7 +1155,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
 
 unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, unsigned int max)
 {
-    DWORD map = 1 << max;
+    DWORD map = 1u << max;
     map |= map - 1;
     map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers;
 
@@ -1171,7 +1176,7 @@ static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semanti
                 break;
 
             case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
-                TRACE("_volume");
+                TRACE("_3d");
                 break;
 
             case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
@@ -1921,9 +1926,9 @@ static void shader_none_disable(void *shader_priv, struct wined3d_context *conte
     priv->vertex_pipe->vp_enable(gl_info, FALSE);
     priv->fragment_pipe->enable_extension(gl_info, FALSE);
 
-    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
-            | (1 << WINED3D_SHADER_TYPE_VERTEX)
-            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+    context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
+            | (1u << WINED3D_SHADER_TYPE_VERTEX)
+            | (1u << WINED3D_SHADER_TYPE_GEOMETRY);
 }
 
 static HRESULT shader_none_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
@@ -1986,6 +1991,7 @@ static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct s
     caps->vs_uniform_count = 0;
     caps->ps_uniform_count = 0;
     caps->ps_1x_max_value = 0.0f;
+    caps->varying_count = 0;
     caps->wined3d_caps = 0;
 }
 
@@ -2034,8 +2040,8 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     unsigned int backend_version;
     const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
 
-    TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
-            shader, byte_code, output_signature, float_const_count);
+    TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u, type %#x, max_version %u.\n",
+            shader, byte_code, output_signature, float_const_count, type, max_version);
 
     list_init(&shader->constantsF);
     list_init(&shader->constantsB);
@@ -2207,7 +2213,7 @@ HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *sh
 }
 
 void find_vs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
-        WORD swizzle_map, struct vs_compile_args *args)
+        WORD swizzle_map, struct vs_compile_args *args, const struct wined3d_d3d_info *d3d_info)
 {
     args->fog_src = state->render_states[WINED3D_RS_FOGTABLEMODE]
             == WINED3D_FOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
@@ -2216,6 +2222,10 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
     args->point_size = state->gl_primitive_type == GL_POINTS;
     args->per_vertex_point_size = shader->reg_maps.point_size;
     args->swizzle_map = swizzle_map;
+    if (d3d_info->emulated_flatshading)
+        args->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
+    else
+        args->flatshading = FALSE;
 }
 
 static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
@@ -2371,7 +2381,7 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d
     {
         const struct wined3d_shader_signature_element *input = &shader->input_signature.elements[i];
 
-        if (!(reg_maps->input_registers & (1 << input->register_idx)) || !input->semantic_name)
+        if (!(reg_maps->input_registers & (1u << input->register_idx)) || !input->semantic_name)
             continue;
 
         shader->u.vs.attributes[input->register_idx].usage =
@@ -2400,8 +2410,10 @@ static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d
 }
 
 void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
-        BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_gl_info *gl_info)
+        BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context)
 {
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     const struct wined3d_texture *texture;
     UINT i;
 
@@ -2528,11 +2540,11 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
         args->color_fixup[i] = texture->resource.format->color_fixup;
 
         if (texture->resource.format_flags & WINED3DFMT_FLAG_SHADOW)
-            args->shadow |= 1 << i;
+            args->shadow |= 1u << i;
 
         /* Flag samplers that need NP2 texcoord fixup. */
         if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
-            args->np2_fixup |= (1 << i);
+            args->np2_fixup |= (1u << i);
     }
     if (shader->reg_maps.shader_version.major >= 3)
     {
@@ -2578,8 +2590,40 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
         }
     }
 
+    if (context->d3d_info->limits.varying_count < wined3d_max_compat_varyings(context->gl_info))
+    {
+        const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
+
+        args->texcoords_initialized = 0;
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            if (vs)
+            {
+                if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.output_registers & (1u << i))
+                    args->texcoords_initialized |= 1u << i;
+            }
+            else
+            {
+                const struct wined3d_stream_info *si = &context->stream_info;
+                unsigned int coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+
+                if ((state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                        & WINED3D_FFP_TCI_MASK
+                        || (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))))
+                    args->texcoords_initialized |= 1u << i;
+            }
+        }
+    }
+    else
+    {
+        args->texcoords_initialized = (1u << MAX_TEXTURES) - 1;
+    }
+
     args->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
             && state->gl_primitive_type == GL_POINTS;
+
+    if (d3d_info->emulated_flatshading)
+        args->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
 }
 
 static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_device *device,
index f5f0b66..148204b 100644 (file)
@@ -28,62 +28,62 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 
 /* DCL usage masks */
 #define WINED3DSP_DCL_USAGE_SHIFT               0
-#define WINED3DSP_DCL_USAGE_MASK                (0xf << WINED3DSP_DCL_USAGE_SHIFT)
+#define WINED3DSP_DCL_USAGE_MASK                (0xfu << WINED3DSP_DCL_USAGE_SHIFT)
 #define WINED3DSP_DCL_USAGEINDEX_SHIFT          16
-#define WINED3DSP_DCL_USAGEINDEX_MASK           (0xf << WINED3DSP_DCL_USAGEINDEX_SHIFT)
+#define WINED3DSP_DCL_USAGEINDEX_MASK           (0xfu << WINED3DSP_DCL_USAGEINDEX_SHIFT)
 
 /* DCL sampler type */
 #define WINED3D_SM1_RESOURCE_TYPE_SHIFT         27
-#define WINED3D_SM1_RESOURCE_TYPE_MASK          (0xf << WINED3D_SM1_RESOURCE_TYPE_SHIFT)
+#define WINED3D_SM1_RESOURCE_TYPE_MASK          (0xfu << WINED3D_SM1_RESOURCE_TYPE_SHIFT)
 
 /* Opcode-related masks */
 #define WINED3DSI_OPCODE_MASK                   0x0000ffff
 
 #define WINED3D_OPCODESPECIFICCONTROL_SHIFT     16
-#define WINED3D_OPCODESPECIFICCONTROL_MASK      (0xff << WINED3D_OPCODESPECIFICCONTROL_SHIFT)
+#define WINED3D_OPCODESPECIFICCONTROL_MASK      (0xffu << WINED3D_OPCODESPECIFICCONTROL_SHIFT)
 
 #define WINED3DSI_INSTLENGTH_SHIFT              24
-#define WINED3DSI_INSTLENGTH_MASK               (0xf << WINED3DSI_INSTLENGTH_SHIFT)
+#define WINED3DSI_INSTLENGTH_MASK               (0xfu << WINED3DSI_INSTLENGTH_SHIFT)
 
-#define WINED3DSI_COISSUE                       (1 << 30)
+#define WINED3DSI_COISSUE                       (0x1u << 30)
 
 #define WINED3DSI_COMMENTSIZE_SHIFT             16
-#define WINED3DSI_COMMENTSIZE_MASK              (0x7fff << WINED3DSI_COMMENTSIZE_SHIFT)
+#define WINED3DSI_COMMENTSIZE_MASK              (0x7fffu << WINED3DSI_COMMENTSIZE_SHIFT)
 
-#define WINED3DSHADER_INSTRUCTION_PREDICATED    (1 << 28)
+#define WINED3DSHADER_INSTRUCTION_PREDICATED    (0x1u << 28)
 
 /* Register number mask */
 #define WINED3DSP_REGNUM_MASK                   0x000007ff
 
 /* Register type masks  */
 #define WINED3DSP_REGTYPE_SHIFT                 28
-#define WINED3DSP_REGTYPE_MASK                  (0x7 << WINED3DSP_REGTYPE_SHIFT)
+#define WINED3DSP_REGTYPE_MASK                  (0x7u << WINED3DSP_REGTYPE_SHIFT)
 #define WINED3DSP_REGTYPE_SHIFT2                8
-#define WINED3DSP_REGTYPE_MASK2                 (0x18 << WINED3DSP_REGTYPE_SHIFT2)
+#define WINED3DSP_REGTYPE_MASK2                 (0x18u << WINED3DSP_REGTYPE_SHIFT2)
 
 /* Relative addressing mask */
 #define WINED3DSHADER_ADDRESSMODE_SHIFT         13
-#define WINED3DSHADER_ADDRESSMODE_MASK          (1 << WINED3DSHADER_ADDRESSMODE_SHIFT)
+#define WINED3DSHADER_ADDRESSMODE_MASK          (0x1u << WINED3DSHADER_ADDRESSMODE_SHIFT)
 
 /* Destination modifier mask */
 #define WINED3DSP_DSTMOD_SHIFT                  20
-#define WINED3DSP_DSTMOD_MASK                   (0xf << WINED3DSP_DSTMOD_SHIFT)
+#define WINED3DSP_DSTMOD_MASK                   (0xfu << WINED3DSP_DSTMOD_SHIFT)
 
 /* Destination shift mask */
 #define WINED3DSP_DSTSHIFT_SHIFT                24
-#define WINED3DSP_DSTSHIFT_MASK                 (0xf << WINED3DSP_DSTSHIFT_SHIFT)
+#define WINED3DSP_DSTSHIFT_MASK                 (0xfu << WINED3DSP_DSTSHIFT_SHIFT)
 
 /* Write mask */
 #define WINED3D_SM1_WRITEMASK_SHIFT             16
-#define WINED3D_SM1_WRITEMASK_MASK              (0xf << WINED3D_SM1_WRITEMASK_SHIFT)
+#define WINED3D_SM1_WRITEMASK_MASK              (0xfu << WINED3D_SM1_WRITEMASK_SHIFT)
 
 /* Swizzle mask */
 #define WINED3DSP_SWIZZLE_SHIFT                 16
-#define WINED3DSP_SWIZZLE_MASK                  (0xff << WINED3DSP_SWIZZLE_SHIFT)
+#define WINED3DSP_SWIZZLE_MASK                  (0xffu << WINED3DSP_SWIZZLE_SHIFT)
 
 /* Source modifier mask */
 #define WINED3DSP_SRCMOD_SHIFT                  24
-#define WINED3DSP_SRCMOD_MASK                   (0xf << WINED3DSP_SRCMOD_SHIFT)
+#define WINED3DSP_SRCMOD_MASK                   (0xfu << WINED3DSP_SRCMOD_SHIFT)
 
 #define WINED3DSP_END                           0x0000ffff
 
@@ -92,8 +92,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 
 enum WINED3DSHADER_ADDRESSMODE_TYPE
 {
-    WINED3DSHADER_ADDRMODE_ABSOLUTE = 0 << WINED3DSHADER_ADDRESSMODE_SHIFT,
-    WINED3DSHADER_ADDRMODE_RELATIVE = 1 << WINED3DSHADER_ADDRESSMODE_SHIFT,
+    WINED3DSHADER_ADDRMODE_ABSOLUTE = 0u << WINED3DSHADER_ADDRESSMODE_SHIFT,
+    WINED3DSHADER_ADDRMODE_RELATIVE = 1u << WINED3DSHADER_ADDRESSMODE_SHIFT,
 };
 
 enum wined3d_sm1_resource_type
@@ -409,7 +409,7 @@ static int shader_get_param(const struct wined3d_sm1_data *priv, const DWORD *pt
     {
         if (priv->shader_version.major < 2)
         {
-            *addr_token = (1 << 31)
+            *addr_token = (1u << 31)
                     | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT2) & WINED3DSP_REGTYPE_MASK2)
                     | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT) & WINED3DSP_REGTYPE_MASK)
                     | (WINED3DSP_NOSWIZZLE << WINED3DSP_SWIZZLE_SHIFT);
index 4881cfa..aa055bf 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode);
 
-#define WINED3D_SM4_INSTRUCTION_MODIFIER        (1 << 31)
+#define WINED3D_SM4_INSTRUCTION_MODIFIER        (0x1u << 31)
 
 #define WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT    24
-#define WINED3D_SM4_INSTRUCTION_LENGTH_MASK     (0x1f << WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT)
+#define WINED3D_SM4_INSTRUCTION_LENGTH_MASK     (0x1fu << WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT)
 
 #define WINED3D_SM4_RESOURCE_TYPE_SHIFT         11
-#define WINED3D_SM4_RESOURCE_TYPE_MASK          (0xf << WINED3D_SM4_RESOURCE_TYPE_SHIFT)
+#define WINED3D_SM4_RESOURCE_TYPE_MASK          (0xfu << WINED3D_SM4_RESOURCE_TYPE_SHIFT)
 
 #define WINED3D_SM4_PRIMITIVE_TYPE_SHIFT        11
-#define WINED3D_SM4_PRIMITIVE_TYPE_MASK         (0x7 << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT)
+#define WINED3D_SM4_PRIMITIVE_TYPE_MASK         (0x7u << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT)
 
 #define WINED3D_SM4_INDEX_TYPE_SHIFT            11
-#define WINED3D_SM4_INDEX_TYPE_MASK             (0x1 << WINED3D_SM4_INDEX_TYPE_SHIFT)
+#define WINED3D_SM4_INDEX_TYPE_MASK             (0x1u << WINED3D_SM4_INDEX_TYPE_SHIFT)
 
 #define WINED3D_SM4_OPCODE_MASK                 0xff
 
-#define WINED3D_SM4_REGISTER_MODIFIER           (1 << 31)
+#define WINED3D_SM4_REGISTER_MODIFIER           (0x1u << 31)
 
 #define WINED3D_SM4_ADDRESSING_SHIFT1           25
-#define WINED3D_SM4_ADDRESSING_MASK1            (0x3 << WINED3D_SM4_ADDRESSING_SHIFT1)
+#define WINED3D_SM4_ADDRESSING_MASK1            (0x3u << WINED3D_SM4_ADDRESSING_SHIFT1)
 
 #define WINED3D_SM4_ADDRESSING_SHIFT0           22
-#define WINED3D_SM4_ADDRESSING_MASK0            (0x3 << WINED3D_SM4_ADDRESSING_SHIFT0)
+#define WINED3D_SM4_ADDRESSING_MASK0            (0x3u << WINED3D_SM4_ADDRESSING_SHIFT0)
 
 #define WINED3D_SM4_REGISTER_ORDER_SHIFT        20
-#define WINED3D_SM4_REGISTER_ORDER_MASK         (0x3 << WINED3D_SM4_REGISTER_ORDER_SHIFT)
+#define WINED3D_SM4_REGISTER_ORDER_MASK         (0x3u << WINED3D_SM4_REGISTER_ORDER_SHIFT)
 
 #define WINED3D_SM4_REGISTER_TYPE_SHIFT         12
-#define WINED3D_SM4_REGISTER_TYPE_MASK          (0xf << WINED3D_SM4_REGISTER_TYPE_SHIFT)
+#define WINED3D_SM4_REGISTER_TYPE_MASK          (0xfu << WINED3D_SM4_REGISTER_TYPE_SHIFT)
 
 #define WINED3D_SM4_SWIZZLE_TYPE_SHIFT          2
-#define WINED3D_SM4_SWIZZLE_TYPE_MASK           (0x3 << WINED3D_SM4_SWIZZLE_TYPE_SHIFT)
+#define WINED3D_SM4_SWIZZLE_TYPE_MASK           (0x3u << WINED3D_SM4_SWIZZLE_TYPE_SHIFT)
 
 #define WINED3D_SM4_IMMCONST_TYPE_SHIFT         0
-#define WINED3D_SM4_IMMCONST_TYPE_MASK          (0x3 << WINED3D_SM4_IMMCONST_TYPE_SHIFT)
+#define WINED3D_SM4_IMMCONST_TYPE_MASK          (0x3u << WINED3D_SM4_IMMCONST_TYPE_SHIFT)
 
 #define WINED3D_SM4_WRITEMASK_SHIFT             4
-#define WINED3D_SM4_WRITEMASK_MASK              (0xf << WINED3D_SM4_WRITEMASK_SHIFT)
+#define WINED3D_SM4_WRITEMASK_MASK              (0xfu << WINED3D_SM4_WRITEMASK_SHIFT)
 
 #define WINED3D_SM4_SWIZZLE_SHIFT               4
-#define WINED3D_SM4_SWIZZLE_MASK                (0xff << WINED3D_SM4_SWIZZLE_SHIFT)
+#define WINED3D_SM4_SWIZZLE_MASK                (0xffu << WINED3D_SM4_SWIZZLE_SHIFT)
 
 #define WINED3D_SM4_VERSION_MAJOR(version)      (((version) >> 4) & 0xf)
 #define WINED3D_SM4_VERSION_MINOR(version)      (((version) >> 0) & 0xf)
index 98440be..e865a92 100644 (file)
@@ -161,7 +161,7 @@ static void state_cullmode(struct wined3d_context *context, const struct wined3d
     }
 }
 
-static void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -172,12 +172,12 @@ static void state_shademode(struct wined3d_context *context, const struct wined3
             checkGLcall("glShadeModel(GL_FLAT)");
             break;
         case WINED3D_SHADE_GOURAUD:
+        /* WINED3D_SHADE_PHONG in practice is the same as WINED3D_SHADE_GOURAUD
+         * in D3D. */
+        case WINED3D_SHADE_PHONG:
             gl_info->gl_ops.gl.p_glShadeModel(GL_SMOOTH);
             checkGLcall("glShadeModel(GL_SMOOTH)");
             break;
-        case WINED3D_SHADE_PHONG:
-            FIXME("WINED3D_SHADE_PHONG isn't supported.\n");
-            break;
         default:
             FIXME("Unrecognized shade mode %#x.\n",
                     state->render_states[WINED3D_RS_SHADEMODE]);
@@ -591,7 +591,7 @@ void state_clipping(struct wined3d_context *context, const struct wined3d_state
      * The enabled / disabled planes are hardcoded into the shader. Update the
      * shader to update the enabled clipplanes. In case of fixed function, we
      * need to update the clipping field from ffp_vertex_settings. */
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
 
     /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
      * of already set values
@@ -1236,7 +1236,7 @@ static void state_colormat(struct wined3d_context *context, const struct wined3d
     }
 
     context->num_untracked_materials = 0;
-    if ((context->stream_info.use_map & (1 << WINED3D_FFP_DIFFUSE))
+    if ((context->stream_info.use_map & (1u << WINED3D_FFP_DIFFUSE))
             && state->render_states[WINED3D_RS_COLORVERTEX])
     {
         TRACE("diff %d, amb %d, emis %d, spec %d\n",
@@ -1389,7 +1389,7 @@ static void state_normalize(struct wined3d_context *context, const struct wined3
      * by zero and is not properly defined in opengl, so avoid it
      */
     if (state->render_states[WINED3D_RS_NORMALIZENORMALS]
-            && (context->stream_info.use_map & (1 << WINED3D_FFP_NORMAL)))
+            && (context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL)))
     {
         gl_info->gl_ops.gl.p_glEnable(GL_NORMALIZE);
         checkGLcall("glEnable(GL_NORMALIZE);");
@@ -1655,11 +1655,17 @@ static void state_scissor(struct wined3d_context *context, const struct wined3d_
  * OpenGL the bias is specified in units of "the smallest value that is
  * guaranteed to produce a resolvable offset for a given implementation". To
  * convert from D3D to GL we need to divide the D3D depth bias by that value.
- * There's no practical way to retrieve that value from a given GL
- * implementation, but the D3D application has essentially the same problem,
- * which makes a guess of the depth buffer format's highest possible value a
- * reasonable guess. Note that SLOPESCALEDEPTHBIAS is a scaling factor for the
- * depth slope, and doesn't need to be scaled. */
+ * We try to detect the value from GL with test draws. On most drivers (r300g,
+ * 600g, Nvidia, i965 on Mesa) the value is 2^23 for fixed point depth buffers,
+ * for r200 and i965 on OSX it is 2^24, for r500 on OSX it is 2^22. For floating
+ * point buffers it is 2^22, 2^23 or 2^24 depending on the GPU. The value does
+ * not depend on the depth buffer precision on any driver.
+ *
+ * Two games that are picky regarding depth bias are Mass Effect 2 (flickering
+ * decals) and F.E.A.R and F.E.A.R. 2 (semi-transparent guns).
+ *
+ * Note that SLOPESCALEDEPTHBIAS is a scaling factor for the depth slope, and
+ * doesn't need to be scaled to account for GL vs D3D differences. */
 static void state_depthbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -1696,10 +1702,13 @@ static void state_depthbias(struct wined3d_context *context, const struct wined3
         {
             if (depth)
             {
-                const struct wined3d_format *fmt = depth->format;
-                scale = powf(2, fmt->depth_size) - 1;
+                if (depth->format_flags & WINED3DFMT_FLAG_FLOAT)
+                    scale = gl_info->float_polyoffset_scale;
+                else
+                    scale = gl_info->fixed_polyoffset_scale;
+
                 TRACE("Depth format %s, using depthbias scale of %.8e.\n",
-                      debug_d3dformat(fmt->id), scale);
+                      debug_d3dformat(depth->format->id), scale);
             }
             else
             {
@@ -3017,7 +3026,7 @@ static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined
 static void tex_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
     DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -3078,7 +3087,7 @@ static void tex_colorop(struct wined3d_context *context, const struct wined3d_st
 void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
     DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     DWORD op, arg1, arg2, arg0;
@@ -3231,7 +3240,7 @@ static void load_tex_coords(const struct wined3d_context *context, const struct
             continue;
         }
 
-        if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
+        if (coordIdx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
         {
             const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
 
@@ -3464,12 +3473,12 @@ static void sampler_texmatrix(struct wined3d_context *context, const struct wine
     {
         const BOOL texIsPow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT);
 
-        if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
+        if (texIsPow2 || (context->lastWasPow2Texture & (1u << sampler)))
         {
             if (texIsPow2)
-                context->lastWasPow2Texture |= 1 << sampler;
+                context->lastWasPow2Texture |= 1u << sampler;
             else
-                context->lastWasPow2Texture &= ~(1 << sampler);
+                context->lastWasPow2Texture &= ~(1u << sampler);
 
             transform_texture(context, state,
                     STATE_TEXTURESTAGE(context->tex_unit_map[sampler], WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
@@ -3685,12 +3694,12 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta
         context->last_was_pshader = FALSE;
     }
 
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void state_geometry_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_GEOMETRY;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY;
 }
 
 static void shader_bumpenv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -3945,7 +3954,7 @@ static inline void unload_numbered_array(struct wined3d_context *context, int i)
     if (gl_info->supported[ARB_INSTANCED_ARRAYS])
         GL_EXTCALL(glVertexAttribDivisor(i, 0));
 
-    context->numbered_array_mask &= ~(1 << i);
+    context->numbered_array_mask &= ~(1u << i);
 }
 
 /* This should match any arrays loaded in loadNumberedArrays
@@ -3974,9 +3983,9 @@ static void load_numbered_arrays(struct wined3d_context *context,
     {
         const struct wined3d_stream_state *stream;
 
-        if (!(stream_info->use_map & (1 << i)))
+        if (!(stream_info->use_map & (1u << i)))
         {
-            if (context->numbered_array_mask & (1 << i))
+            if (context->numbered_array_mask & (1u << i))
                 unload_numbered_array(context, i);
             if (!use_vs(state) && i == WINED3D_FFP_DIFFUSE)
                 GL_EXTCALL(glVertexAttrib4f(i, 1.0f, 1.0f, 1.0f, 1.0f));
@@ -3998,7 +4007,7 @@ static void load_numbered_arrays(struct wined3d_context *context,
         {
             /* Unload instanced arrays, they will be loaded using
              * immediate mode instead. */
-            if (context->numbered_array_mask & (1 << i))
+            if (context->numbered_array_mask & (1u << i))
                 unload_numbered_array(context, i);
             continue;
         }
@@ -4023,10 +4032,10 @@ static void load_numbered_arrays(struct wined3d_context *context,
                     stream_info->elements[i].stride, stream_info->elements[i].data.addr
                     + state->load_base_vertex_index * stream_info->elements[i].stride));
 
-            if (!(context->numbered_array_mask & (1 << i)))
+            if (!(context->numbered_array_mask & (1u << i)))
             {
                 GL_EXTCALL(glEnableVertexAttribArray(i));
-                context->numbered_array_mask |= (1 << i);
+                context->numbered_array_mask |= (1u << i);
             }
         }
         else
@@ -4041,7 +4050,7 @@ static void load_numbered_arrays(struct wined3d_context *context,
                 ptr += (ULONG_PTR)buffer_get_sysmem(stream->buffer, context);
             }
 
-            if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
+            if (context->numbered_array_mask & (1u << i)) unload_numbered_array(context, i);
 
             switch (stream_info->elements[i].format->id)
             {
@@ -4065,9 +4074,9 @@ static void load_numbered_arrays(struct wined3d_context *context,
                     if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
                     {
                         const DWORD *src = (const DWORD *)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(i, (GLubyte *)&c));
                         break;
                     }
@@ -4163,8 +4172,8 @@ static void load_vertex_data(struct wined3d_context *context,
     context->instance_count = 0;
 
     /* Blend Data ---------------------------------------------- */
-    if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
-            || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
+    if ((si->use_map & (1u << WINED3D_FFP_BLENDWEIGHT))
+            || si->use_map & (1u << WINED3D_FFP_BLENDINDICES))
     {
         e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
 
@@ -4195,7 +4204,7 @@ static void load_vertex_data(struct wined3d_context *context,
 
             checkGLcall("glWeightPointerARB");
 
-            if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
+            if (si->use_map & (1u << WINED3D_FFP_BLENDINDICES))
             {
                 static BOOL warned;
                 if (!warned)
@@ -4228,7 +4237,7 @@ static void load_vertex_data(struct wined3d_context *context,
     }
 
     /* Point Size ----------------------------------------------*/
-    if (si->use_map & (1 << WINED3D_FFP_PSIZE))
+    if (si->use_map & (1u << WINED3D_FFP_PSIZE))
     {
         /* no such functionality in the fixed function GL pipeline */
         TRACE("Cannot change ptSize here in openGl\n");
@@ -4236,7 +4245,7 @@ static void load_vertex_data(struct wined3d_context *context,
     }
 
     /* Vertex Pointers -----------------------------------------*/
-    if (si->use_map & (1 << WINED3D_FFP_POSITION))
+    if (si->use_map & (1u << WINED3D_FFP_POSITION))
     {
         e = &si->elements[WINED3D_FFP_POSITION];
 
@@ -4258,7 +4267,7 @@ static void load_vertex_data(struct wined3d_context *context,
     }
 
     /* Normals -------------------------------------------------*/
-    if (si->use_map & (1 << WINED3D_FFP_NORMAL))
+    if (si->use_map & (1u << WINED3D_FFP_NORMAL))
     {
         e = &si->elements[WINED3D_FFP_NORMAL];
 
@@ -4285,7 +4294,7 @@ static void load_vertex_data(struct wined3d_context *context,
     }
 
     /* Diffuse Colour --------------------------------------------*/
-    if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
+    if (si->use_map & (1u << WINED3D_FFP_DIFFUSE))
     {
         e = &si->elements[WINED3D_FFP_DIFFUSE];
 
@@ -4313,7 +4322,7 @@ static void load_vertex_data(struct wined3d_context *context,
     }
 
     /* Specular Colour ------------------------------------------*/
-    if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
+    if (si->use_map & (1u << WINED3D_FFP_SPECULAR))
     {
         TRACE("setting specular colour\n");
 
@@ -4544,7 +4553,7 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     }
 
     context->last_was_vshader = useVertexShaderFunction;
-    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
 
     if (updateFog)
         context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE));
@@ -4561,7 +4570,7 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
 
         if (use_ps(state) && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1
                 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3)
-            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
+            context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
     }
 }
 
@@ -4977,7 +4986,6 @@ const struct StateEntryTemplate misc_state_template[] =
     { STATE_RENDER(WINED3D_RS_WRAPU),                     { STATE_RENDER(WINED3D_RS_WRAPU),                     state_wrapu         }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_WRAPV),                     { STATE_RENDER(WINED3D_RS_WRAPV),                     state_wrapv         }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_FILLMODE),                  { STATE_RENDER(WINED3D_RS_FILLMODE),                  state_fillmode      }, WINED3D_GL_EXT_NONE             },
-    { STATE_RENDER(WINED3D_RS_SHADEMODE),                 { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode     }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_LINEPATTERN),               { STATE_RENDER(WINED3D_RS_LINEPATTERN),               state_linepattern   }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_MONOENABLE),                { STATE_RENDER(WINED3D_RS_MONOENABLE),                state_monoenable    }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_ROP2),                      { STATE_RENDER(WINED3D_RS_ROP2),                      state_rop2          }, WINED3D_GL_EXT_NONE             },
@@ -5585,6 +5593,7 @@ static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
     { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_FOGSTART),                  { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend   }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_FOGEND),                    { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SHADEMODE),                 { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode     }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
@@ -5627,10 +5636,16 @@ static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3
         caps->raster_caps |= WINED3DPRASTERCAPS_FOGRANGE;
 }
 
+static DWORD vp_ffp_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
+}
+
 const struct wined3d_vertex_pipe_ops ffp_vertex_pipe =
 {
     ffp_enable,
     vp_ffp_get_caps,
+    vp_ffp_get_emul_mask,
     ffp_alloc,
     ffp_free,
     vp_ffp_states,
@@ -5677,6 +5692,11 @@ static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct
     caps->MaxSimultaneousTextures = gl_info->limits.textures;
 }
 
+static DWORD ffp_fragment_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
+}
+
 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
 {
     if (TRACE_ON(d3d))
@@ -5708,6 +5728,7 @@ static void ffp_none_context_free(struct wined3d_context *context)
 const struct fragment_pipeline ffp_fragment_pipeline = {
     ffp_enable,
     ffp_fragment_get_caps,
+    ffp_fragment_get_emul_mask,
     ffp_alloc,
     ffp_free,
     ffp_none_context_alloc,
@@ -5730,10 +5751,16 @@ static void vp_none_get_caps(const struct wined3d_gl_info *gl_info, struct wined
     memset(caps, 0, sizeof(*caps));
 }
 
+static DWORD vp_none_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return 0;
+}
+
 const struct wined3d_vertex_pipe_ops none_vertex_pipe =
 {
     none_enable,
     vp_none_get_caps,
+    vp_none_get_emul_mask,
     none_alloc,
     none_free,
     NULL,
@@ -5744,6 +5771,11 @@ static void fp_none_get_caps(const struct wined3d_gl_info *gl_info, struct fragm
     memset(caps, 0, sizeof(*caps));
 }
 
+static DWORD fp_none_get_emul_mask(const struct wined3d_gl_info *gl_info)
+{
+    return 0;
+}
+
 static BOOL fp_none_color_fixup_supported(struct color_fixup_desc fixup)
 {
     return is_identity_fixup(fixup);
@@ -5753,6 +5785,7 @@ const struct fragment_pipeline none_fragment_pipe =
 {
     none_enable,
     fp_none_get_caps,
+    fp_none_get_emul_mask,
     none_alloc,
     none_free,
     ffp_none_context_alloc,
index ff620fb..4938bed 100644 (file)
@@ -223,7 +223,7 @@ fail:
 
 static inline void stateblock_set_bits(DWORD *map, UINT map_size)
 {
-    DWORD mask = (1 << (map_size & 0x1f)) - 1;
+    DWORD mask = (1u << (map_size & 0x1f)) - 1;
     memset(map, 0xff, (map_size >> 5) * sizeof(*map));
     if (mask) map[map_size >> 5] = mask;
 }
@@ -273,14 +273,14 @@ static void stateblock_savedstates_set_pixel(struct wined3d_saved_states *states
     for (i = 0; i < sizeof(pixel_states_render) / sizeof(*pixel_states_render); ++i)
     {
         DWORD rs = pixel_states_render[i];
-        states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
+        states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
     }
 
     for (i = 0; i < sizeof(pixel_states_texture) / sizeof(*pixel_states_texture); ++i)
-        texture_mask |= 1 << pixel_states_texture[i];
+        texture_mask |= 1u << pixel_states_texture[i];
     for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
     for (i = 0; i < sizeof(pixel_states_sampler) / sizeof(*pixel_states_sampler); ++i)
-        sampler_mask |= 1 << pixel_states_sampler[i];
+        sampler_mask |= 1u << pixel_states_sampler[i];
     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
     states->pixelShaderConstantsB = 0xffff;
     states->pixelShaderConstantsI = 0xffff;
@@ -300,14 +300,14 @@ static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *state
     for (i = 0; i < sizeof(vertex_states_render) / sizeof(*vertex_states_render); ++i)
     {
         DWORD rs = vertex_states_render[i];
-        states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
+        states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
     }
 
     for (i = 0; i < sizeof(vertex_states_texture) / sizeof(*vertex_states_texture); ++i)
-        texture_mask |= 1 << vertex_states_texture[i];
+        texture_mask |= 1u << vertex_states_texture[i];
     for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
     for (i = 0; i < sizeof(vertex_states_sampler) / sizeof(*vertex_states_sampler); ++i)
-        sampler_mask |= 1 << vertex_states_sampler[i];
+        sampler_mask |= 1u << vertex_states_sampler[i];
     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
     states->vertexShaderConstantsB = 0xffff;
     states->vertexShaderConstantsI = 0xffff;
@@ -355,7 +355,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
 
     for (i = 0; i < MAX_CONST_I; ++i)
     {
-        if (stateblock->changed.vertexShaderConstantsI & (1 << i))
+        if (stateblock->changed.vertexShaderConstantsI & (1u << i))
         {
             stateblock->contained_vs_consts_i[stateblock->num_contained_vs_consts_i] = i;
             ++stateblock->num_contained_vs_consts_i;
@@ -364,7 +364,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
 
     for (i = 0; i < MAX_CONST_B; ++i)
     {
-        if (stateblock->changed.vertexShaderConstantsB & (1 << i))
+        if (stateblock->changed.vertexShaderConstantsB & (1u << i))
         {
             stateblock->contained_vs_consts_b[stateblock->num_contained_vs_consts_b] = i;
             ++stateblock->num_contained_vs_consts_b;
@@ -382,7 +382,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
 
     for (i = 0; i < MAX_CONST_I; ++i)
     {
-        if (stateblock->changed.pixelShaderConstantsI & (1 << i))
+        if (stateblock->changed.pixelShaderConstantsI & (1u << i))
         {
             stateblock->contained_ps_consts_i[stateblock->num_contained_ps_consts_i] = i;
             ++stateblock->num_contained_ps_consts_i;
@@ -391,7 +391,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
 
     for (i = 0; i < MAX_CONST_B; ++i)
     {
-        if (stateblock->changed.pixelShaderConstantsB & (1 << i))
+        if (stateblock->changed.pixelShaderConstantsB & (1u << i))
         {
             stateblock->contained_ps_consts_b[stateblock->num_contained_ps_consts_b] = i;
             ++stateblock->num_contained_ps_consts_b;
index f5f99e8..6d99f33 100644 (file)
@@ -397,9 +397,9 @@ void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3
 /* Works correctly only for <= 4 bpp formats. */
 static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
 {
-    masks[0] = ((1 << format->red_size) - 1) << format->red_offset;
-    masks[1] = ((1 << format->green_size) - 1) << format->green_offset;
-    masks[2] = ((1 << format->blue_size) - 1) << format->blue_offset;
+    masks[0] = ((1u << format->red_size) - 1) << format->red_offset;
+    masks[1] = ((1u << format->green_size) - 1) << format->green_offset;
+    masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset;
 }
 
 static HRESULT surface_create_dib_section(struct wined3d_surface *surface)
@@ -410,7 +410,9 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface)
     BITMAPINFO *b_info;
     int extraline = 0;
     DWORD *masks;
+#if defined(STAGING_CSMT)
     UINT row_pitch, slice_pitch;
+#endif /* STAGING_CSMT */
 
     TRACE("surface %p.\n", surface);
 
@@ -435,7 +437,7 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface)
         default:
             /* Allocate extra space for a palette. */
             b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                    sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format->byte_count * 8)));
+                    sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1u << (format->byte_count * 8)));
             break;
     }
 
@@ -456,11 +458,18 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface)
 
     b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
+#if defined(STAGING_CSMT)
     wined3d_resource_get_pitch(&surface->resource, &row_pitch, &slice_pitch);
     b_info->bmiHeader.biWidth = row_pitch / format->byte_count;
     b_info->bmiHeader.biHeight = 0 - surface->resource.height - extraline;
     b_info->bmiHeader.biSizeImage = (surface->resource.height + extraline)
             * row_pitch;
+#else  /* STAGING_CSMT */
+    b_info->bmiHeader.biWidth = wined3d_surface_get_pitch(surface) / format->byte_count;
+    b_info->bmiHeader.biHeight = 0 - surface->resource.height - extraline;
+    b_info->bmiHeader.biSizeImage = (surface->resource.height + extraline)
+            * wined3d_surface_get_pitch(surface);
+#endif /* STAGING_CSMT */
     b_info->bmiHeader.biPlanes = 1;
     b_info->bmiHeader.biBitCount = format->byte_count * 8;
 
@@ -836,7 +845,11 @@ static void surface_unmap(struct wined3d_surface *surface)
     }
 
     if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container)
-        surface_load_location(surface, surface->container->resource.draw_binding);
+    {
+        context = context_acquire(device, surface);
+        surface_load_location(surface, context, surface->container->resource.draw_binding);
+        context_release(context);
+    }
     else if (surface->container->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
         FIXME("Depth / stencil buffer locking is not implemented.\n");
 #endif /* STAGING_CSMT */
@@ -890,14 +903,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     if (src_mask & WINED3DFMT_FLAG_STENCIL)
         gl_mask |= GL_STENCIL_BUFFER_BIT;
 
-#if !defined(STAGING_CSMT)
-    /* Make sure the locations are up-to-date. Loading the destination
-     * surface isn't required if the entire surface is overwritten. */
-    surface_load_location(src_surface, src_location);
-    if (!surface_is_full_rect(dst_surface, dst_rect))
-        surface_load_location(dst_surface, dst_location);
-
-#endif /* STAGING_CSMT */
     context = context_acquire(device, NULL);
     if (!context->valid)
     {
@@ -906,14 +911,18 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
         return;
     }
 
-#if defined(STAGING_CSMT)
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. */
+#if defined(STAGING_CSMT)
     wined3d_resource_load_location(&src_surface->resource, context, src_location);
     if (!surface_is_full_rect(dst_surface, dst_rect))
         wined3d_resource_load_location(&dst_surface->resource, context, dst_location);
-
+#else  /* STAGING_CSMT */
+    surface_load_location(src_surface, context, src_location);
+    if (!surface_is_full_rect(dst_surface, dst_rect))
+        surface_load_location(dst_surface, context, dst_location);
 #endif /* STAGING_CSMT */
+
     gl_info = context->gl_info;
 
     context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location);
@@ -953,7 +962,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     context_release(context);
 }
 
-#if defined(STAGING_CSMT)
 /* Blit between surface locations. Onscreen on different swapchains is not supported.
  * Depth / stencil is not supported. Context activation is done by the caller. */
 static void surface_blt_fbo(const struct wined3d_device *device,
@@ -962,18 +970,8 @@ static void surface_blt_fbo(const struct wined3d_device *device,
         struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
 {
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-    struct wined3d_surface *required_rt, *restore_rt;
-#else  /* STAGING_CSMT */
-/* Blit between surface locations. Onscreen on different swapchains is not supported.
- * Depth / stencil is not supported. */
-static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_texture_filter_type filter,
-        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in,
-        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
-{
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-#endif /* STAGING_CSMT */
+    struct wined3d_context *context = old_ctx;
+    struct wined3d_surface *required_rt, *restore_rt = NULL;
     RECT src_rect, dst_rect;
     GLenum gl_filter;
     GLenum buffer;
@@ -1016,6 +1014,11 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te
     wined3d_resource_load_location(&src_surface->resource, old_ctx, src_location);
     if (!surface_is_full_rect(dst_surface, &dst_rect))
         wined3d_resource_load_location(&dst_surface->resource, old_ctx, dst_location);
+#else  /* STAGING_CSMT */
+    surface_load_location(src_surface, old_ctx, src_location);
+    if (!surface_is_full_rect(dst_surface, &dst_rect))
+        surface_load_location(dst_surface, old_ctx, dst_location);
+#endif /* STAGING_CSMT */
 
     if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface;
     else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface;
@@ -1026,20 +1029,6 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te
         restore_rt = old_ctx->current_rt;
         context = context_acquire(device, required_rt);
     }
-    else
-    {
-        restore_rt = NULL;
-        context = old_ctx;
-    }
-#else  /* STAGING_CSMT */
-    surface_load_location(src_surface, src_location);
-    if (!surface_is_full_rect(dst_surface, &dst_rect))
-        surface_load_location(dst_surface, dst_location);
-
-    if (src_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, src_surface);
-    else if (dst_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, dst_surface);
-    else context = context_acquire(device, NULL);
-#endif /* STAGING_CSMT */
 
     if (!context->valid)
     {
@@ -1102,16 +1091,8 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te
             && dst_surface->container->swapchain->front_buffer == dst_surface->container))
         gl_info->gl_ops.gl.p_glFlush();
 
-#if defined(STAGING_CSMT)
     if (restore_rt)
-    {
-        context_release(context);
-        context = context_acquire(device, restore_rt);
-        context_release(context);
-    }
-#else  /* STAGING_CSMT */
-    context_release(context);
-#endif /* STAGING_CSMT */
+        context_restore(context, restore_rt);
 }
 
 static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
@@ -1134,6 +1115,10 @@ static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined
             if (!((dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FBO_ATTACHABLE)
                     || (dst_usage & WINED3DUSAGE_RENDERTARGET)))
                 return FALSE;
+            if (!(src_format->id == dst_format->id
+                    || (is_identity_fixup(src_format->color_fixup)
+                    && is_identity_fixup(dst_format->color_fixup))))
+                return FALSE;
             break;
 
         case WINED3D_BLIT_OP_DEPTH_BLIT:
@@ -1141,17 +1126,18 @@ static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined
                 return FALSE;
             if (!(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
                 return FALSE;
+            /* Accept pure swizzle fixups for depth formats. In general we
+             * ignore the stencil component (if present) at the moment and the
+             * swizzle is not relevant with just the depth component. */
+            if (is_complex_fixup(src_format->color_fixup) || is_complex_fixup(dst_format->color_fixup)
+                    || is_scaling_fixup(src_format->color_fixup) || is_scaling_fixup(dst_format->color_fixup))
+                return FALSE;
             break;
 
         default:
             return FALSE;
     }
 
-    if (!(src_format->id == dst_format->id
-            || (is_identity_fixup(src_format->color_fixup)
-            && is_identity_fixup(dst_format->color_fixup))))
-        return FALSE;
-
     return TRUE;
 }
 
@@ -1221,19 +1207,6 @@ static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DW
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
-        struct wined3d_surface *render_target)
-{
-    TRACE("surface %p, render_target %p.\n", surface, render_target);
-
-    /* TODO: Check surface sizes, pools, etc. */
-
-    if (render_target->resource.multisample_type)
-        return WINED3DERR_INVALIDCALL;
-
-    return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT);
-}
-
 #if !defined(STAGING_CSMT)
 /* Context activation is done by the caller. */
 static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
@@ -1266,12 +1239,12 @@ static void surface_unload(struct wined3d_resource *resource)
 
     TRACE("surface %p.\n", surface);
 
-#if defined(STAGING_CSMT)
     context = context_acquire(device, NULL);
     gl_info = context->gl_info;
 
     if (resource->pool == WINED3D_POOL_DEFAULT)
     {
+#if defined(STAGING_CSMT)
         /* Default pool resources are supposed to be destroyed before Reset is called.
          * Implicit resources stay however. So this means we have an implicit render target
          * or depth stencil. The content may be destroyed, but we still have to tear down
@@ -1279,8 +1252,6 @@ static void surface_unload(struct wined3d_resource *resource)
         wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DISCARDED);
         wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_DISCARDED);
 #else  /* STAGING_CSMT */
-    if (resource->pool == WINED3D_POOL_DEFAULT)
-    {
         /* Default pool resources are supposed to be destroyed before Reset is called.
          * Implicit resources stay however. So this means we have an implicit render target
          * or depth stencil. The content may be destroyed, but we still have to tear down
@@ -1311,13 +1282,10 @@ static void surface_unload(struct wined3d_resource *resource)
     }
 #else  /* STAGING_CSMT */
         surface_prepare_map_memory(surface);
-        surface_load_location(surface, surface->resource.map_binding);
+        surface_load_location(surface, context, surface->resource.map_binding);
         surface_invalidate_location(surface, ~surface->resource.map_binding);
     }
 
-    context = context_acquire(device, NULL);
-    gl_info = context->gl_info;
-
     /* Destroy PBOs, but load them into real sysmem before */
     if (surface->pbo)
         surface_remove_pbo(surface, gl_info);
@@ -1352,6 +1320,19 @@ static void surface_unload(struct wined3d_resource *resource)
     resource_unload(resource);
 }
 
+static HRESULT surface_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)
+{
+    ERR("Not supported on sub-resources.\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+static HRESULT surface_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    ERR("Not supported on sub-resources.\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
 #if defined(STAGING_CSMT)
 static void wined3d_surface_location_invalidated(struct wined3d_resource *resource, DWORD location)
 {
@@ -1374,6 +1355,8 @@ static const struct wined3d_resource_ops surface_resource_ops =
     surface_resource_incref,
     surface_resource_decref,
     surface_unload,
+    surface_resource_sub_resource_map,
+    surface_resource_sub_resource_unmap,
 };
 
 static const struct wined3d_surface_ops surface_ops =
@@ -1501,6 +1484,7 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
         void *mem;
         GLenum gl_format = format->glFormat;
         GLenum gl_type = format->glType;
+#if defined(STAGING_CSMT)
         UINT src_pitch = 0;
         UINT dst_row_pitch, dst_slice_pitch;
 
@@ -1509,6 +1493,16 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
             unsigned char alignment = surface->resource.device->surface_alignment;
             src_pitch = format->byte_count * surface->pow2Width;
             wined3d_resource_get_pitch(&surface->resource, &dst_row_pitch, &dst_slice_pitch);
+#else  /* STAGING_CSMT */
+        int src_pitch = 0;
+        int dst_pitch = 0;
+
+        if (surface->flags & SFLAG_NONPOW2)
+        {
+            unsigned char alignment = surface->resource.device->surface_alignment;
+            src_pitch = format->byte_count * surface->pow2Width;
+            dst_pitch = wined3d_surface_get_pitch(surface);
+#endif /* STAGING_CSMT */
             src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
             mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * surface->pow2Height);
         }
@@ -1595,12 +1589,21 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
              * won't be released, and doesn't have to be re-read. */
             src_data = mem;
             dst_data = data.addr;
+#if defined(STAGING_CSMT)
             TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_row_pitch);
             for (y = 0; y < surface->resource.height; ++y)
             {
                 memcpy(dst_data, src_data, dst_row_pitch);
                 src_data += src_pitch;
                 dst_data += dst_row_pitch;
+#else  /* STAGING_CSMT */
+            TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_pitch);
+            for (y = 0; y < surface->resource.height; ++y)
+            {
+                memcpy(dst_data, src_data, dst_pitch);
+                src_data += src_pitch;
+                dst_data += dst_pitch;
+#endif /* STAGING_CSMT */
             }
 
             HeapFree(GetProcessHeap(), 0, mem);
@@ -1722,29 +1725,19 @@ void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct w
     }
 }
 
-#if defined(STAGING_CSMT)
-BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect)
+static BOOL surface_check_block_align(struct wined3d_surface *surface, const struct wined3d_box *box)
 {
-    struct wined3d_box box;
-
-    if (!rect)
-        return wined3d_resource_check_block_align(&surface->resource, NULL);
+#if defined(STAGING_CSMT)
+    return wined3d_resource_check_block_align(&surface->resource, box);
+}
 
-    box.left = rect->left;
-    box.top = rect->top;
-    box.front = 0;
-    box.right = rect->right;
-    box.bottom = rect->bottom;
-    box.back = 1;
-    return wined3d_resource_check_block_align(&surface->resource, &box);
+BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect)
 #else  /* STAGING_CSMT */
-static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect)
-{
     UINT width_mask, height_mask;
 
-    if (!rect->left && !rect->top
-            && rect->right == surface->resource.width
-            && rect->bottom == surface->resource.height)
+    if (!box->left && !box->top
+            && box->right == surface->resource.width
+            && box->bottom == surface->resource.height)
         return TRUE;
 
     /* This assumes power of two block sizes, but NPOT block sizes would be
@@ -1752,12 +1745,19 @@ static BOOL surface_check_block_align(struct wined3d_surface *surface, const REC
     width_mask = surface->resource.format->block_width - 1;
     height_mask = surface->resource.format->block_height - 1;
 
-    if (!(rect->left & width_mask) && !(rect->top & height_mask)
-            && !(rect->right & width_mask) && !(rect->bottom & height_mask))
+    if (!(box->left & width_mask) && !(box->top & height_mask)
+            && !(box->right & width_mask) && !(box->bottom & height_mask))
         return TRUE;
 
     return FALSE;
+}
+
+static BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect)
 #endif /* STAGING_CSMT */
+{
+    struct wined3d_box box = {rect->left, rect->top, rect->right, rect->bottom, 0, 1};
+
+    return surface_check_block_align(surface, &box);
 }
 
 HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point,
@@ -1772,7 +1772,11 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
     UINT update_w, update_h;
     UINT dst_w, dst_h;
     RECT r, dst_rect;
+#if defined(STAGING_CSMT)
     UINT src_row_pitch, src_slice_pitch;
+#else  /* STAGING_CSMT */
+    UINT src_pitch;
+#endif /* STAGING_CSMT */
     POINT p;
 
     TRACE("dst_surface %p, dst_point %s, src_surface %p, src_rect %s.\n",
@@ -1830,14 +1834,14 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
         return WINED3DERR_INVALIDCALL;
     }
 
-    if ((src_fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(src_surface, src_rect))
+    if ((src_fmt_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_fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(dst_surface, &dst_rect))
+    if ((dst_fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align_rect(dst_surface, &dst_rect))
     {
         WARN("Destination rectangle not block-aligned.\n");
         return WINED3DERR_INVALIDCALL;
@@ -1869,12 +1873,6 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
     wined3d_texture_bind_and_dirtify(dst_surface->container, context, FALSE);
 
     wined3d_resource_get_memory(&src_surface->resource, src_surface->resource.locations, &data);
-#else  /* STAGING_CSMT */
-        surface_load_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB);
-    wined3d_texture_bind_and_dirtify(dst_surface->container, context, FALSE);
-
-    surface_get_memory(src_surface, &data, src_surface->locations);
-#endif /* STAGING_CSMT */
     wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch);
 
     wined3d_surface_upload_data(dst_surface, gl_info, src_format, src_rect,
@@ -1882,10 +1880,20 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
 
     context_release(context);
 
-#if defined(STAGING_CSMT)
     wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB);
     wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB);
 #else  /* STAGING_CSMT */
+        surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_texture_bind_and_dirtify(dst_surface->container, context, FALSE);
+
+    surface_get_memory(src_surface, &data, src_surface->locations);
+    src_pitch = wined3d_surface_get_pitch(src_surface);
+
+    wined3d_surface_upload_data(dst_surface, gl_info, src_format, src_rect,
+            src_pitch, dst_point, FALSE, wined3d_const_bo_address(&data));
+
+    context_release(context);
+
     surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB);
     surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB);
 #endif /* STAGING_CSMT */
@@ -1992,12 +2000,8 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface)
     return GL_BACK;
 }
 
-#if defined(STAGING_CSMT)
 /* Context activation is done by the caller. */
 void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb)
-#else  /* STAGING_CSMT */
-void surface_load(struct wined3d_surface *surface, BOOL srgb)
-#endif /* STAGING_CSMT */
 {
     DWORD location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
 
@@ -2023,7 +2027,7 @@ void surface_load(struct wined3d_surface *surface, BOOL srgb)
     }
     TRACE("Reloading because surface is dirty.\n");
 
-    surface_load_location(surface, location);
+    surface_load_location(surface, context, location);
 #endif /* STAGING_CSMT */
     surface_evict_sysmem(surface);
 }
@@ -2044,21 +2048,21 @@ static inline unsigned short float_32_to_16(const float *in)
     if (isinf(*in))
         return (*in < 0.0f ? 0xfc00 : 0x7c00);
 
-    if (tmp < powf(2, 10))
+    if (tmp < (float)(1u << 10))
     {
         do
         {
             tmp = tmp * 2.0f;
             exp--;
-        } while (tmp < powf(2, 10));
+        } while (tmp < (float)(1u << 10));
     }
-    else if (tmp >= powf(2, 11))
+    else if (tmp >= (float)(1u << 11))
     {
         do
         {
             tmp /= 2.0f;
             exp++;
-        } while (tmp >= powf(2, 11));
+        } while (tmp >= (float)(1u << 11));
     }
 
     mantissa = (unsigned int)tmp;
@@ -2145,38 +2149,6 @@ struct wined3d_resource * CDECL wined3d_surface_get_resource(struct wined3d_surf
     return &surface->resource;
 }
 
-HRESULT CDECL wined3d_surface_get_blt_status(const struct wined3d_surface *surface, DWORD flags)
-{
-    TRACE("surface %p, flags %#x.\n", surface, flags);
-
-    switch (flags)
-    {
-        case WINEDDGBS_CANBLT:
-        case WINEDDGBS_ISBLTDONE:
-            return WINED3D_OK;
-
-        default:
-            return WINED3DERR_INVALIDCALL;
-    }
-}
-
-HRESULT CDECL wined3d_surface_get_flip_status(const struct wined3d_surface *surface, DWORD flags)
-{
-    TRACE("surface %p, flags %#x.\n", surface, flags);
-
-    /* XXX: DDERR_INVALIDSURFACETYPE */
-
-    switch (flags)
-    {
-        case WINEDDGFS_CANFLIP:
-        case WINEDDGFS_ISFLIPDONE:
-            return WINED3D_OK;
-
-        default:
-            return WINED3DERR_INVALIDCALL;
-    }
-}
-
 HRESULT CDECL wined3d_surface_is_lost(const struct wined3d_surface *surface)
 {
     TRACE("surface %p.\n", surface);
@@ -2193,6 +2165,32 @@ HRESULT CDECL wined3d_surface_restore(struct wined3d_surface *surface)
     return WINED3D_OK;
 }
 
+DWORD CDECL wined3d_surface_get_pitch(const struct wined3d_surface *surface)
+{
+#if defined(STAGING_CSMT)
+    UINT row_pitch, slice_pitch;
+    const struct wined3d_resource *resource = &surface->resource;
+    wined3d_resource_get_pitch(resource, &row_pitch, &slice_pitch);
+    return row_pitch;
+#else  /* STAGING_CSMT */
+    unsigned int alignment;
+    DWORD pitch;
+
+    TRACE("surface %p.\n", surface);
+
+    if (surface->pitch)
+        return surface->pitch;
+
+    alignment = surface->resource.device->surface_alignment;
+    pitch = wined3d_format_calculate_pitch(surface->resource.format, surface->resource.width);
+    pitch = (pitch + alignment - 1) & ~(alignment - 1);
+
+    TRACE("Returning %u.\n", pitch);
+
+    return pitch;
+#endif /* STAGING_CSMT */
+}
+
 HRESULT CDECL wined3d_surface_set_overlay_position(struct wined3d_surface *surface, LONG x, LONG y)
 {
     LONG w, h;
@@ -2360,9 +2358,6 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface,
 
 #if defined(STAGING_CSMT)
     if ((surface->resource.user_memory = mem))
-#else  /* STAGING_CSMT */
-    if ((surface->user_memory = mem))
-#endif /* STAGING_CSMT */
     {
         surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
         valid_location = WINED3D_LOCATION_USER_MEMORY;
@@ -2379,9 +2374,30 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface,
     else
     {
         /* User memory surfaces don't have the regular surface alignment. */
-        surface->resource.size = wined3d_format_calculate_size(texture_resource->format, 1, width, height, 1);
+        surface->resource.size = wined3d_format_calculate_size(texture_resource->format,
+                1, width, height, 1);
         surface->resource.custom_row_pitch = wined3d_format_calculate_pitch(texture_resource->format, width);
-        surface->resource.custom_slice_pitch = surface->resource.custom_row_pitch * surface->resource.height; /* FIXME */
+#else  /* STAGING_CSMT */
+    if ((surface->user_memory = mem))
+    {
+        surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
+        valid_location = WINED3D_LOCATION_USER_MEMORY;
+    }
+    surface->pitch = pitch;
+    surface->resource.format = texture_resource->format;
+    surface->resource.multisample_type = texture_resource->multisample_type;
+    surface->resource.multisample_quality = texture_resource->multisample_quality;
+    if (surface->pitch)
+    {
+        surface->resource.size = height * surface->pitch;
+    }
+    else
+    {
+        /* User memory surfaces don't have the regular surface alignment. */
+        surface->resource.size = wined3d_format_calculate_size(texture_resource->format,
+                1, width, height, 1);
+        surface->pitch = wined3d_format_calculate_pitch(texture_resource->format, width);
+#endif /* STAGING_CSMT */
     }
 
     /* The format might be changed to a format that needs conversion.
@@ -2473,10 +2489,10 @@ static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst,
         for (x = 0; x < w; ++x)
         {
             WORD pixel = src_line[x];
-            dst_line[x] = 0xff000000
-                    | convert_5to8[(pixel & 0xf800) >> 11] << 16
-                    | convert_6to8[(pixel & 0x07e0) >> 5] << 8
-                    | convert_5to8[(pixel & 0x001f)];
+            dst_line[x] = 0xff000000u
+                    | convert_5to8[(pixel & 0xf800u) >> 11] << 16
+                    | convert_6to8[(pixel & 0x07e0u) >> 5] << 8
+                    | convert_5to8[(pixel & 0x001fu)];
         }
     }
 }
@@ -2959,14 +2975,6 @@ HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface)
     memset(&surface->lockedRect, 0, sizeof(surface->lockedRect));
 
     return hr;
-}
-
-HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
-        struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags)
-{
-    struct wined3d_box box;
-    const struct wined3d_format *format = surface->resource.format;
-    unsigned int fmt_flags = surface->container->resource.format_flags;
 #else  /* STAGING_CSMT */
     TRACE("surface %p.\n", surface);
 
@@ -2980,20 +2988,22 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
     surface->surface_ops->surface_unmap(surface);
 
     return WINED3D_OK;
+#endif /* STAGING_CSMT */
 }
 
 HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
-        struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags)
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
 {
     const struct wined3d_format *format = surface->resource.format;
     unsigned int fmt_flags = surface->container->resource.format_flags;
+#if !defined(STAGING_CSMT)
     struct wined3d_device *device = surface->resource.device;
     struct wined3d_context *context;
     const struct wined3d_gl_info *gl_info;
     BYTE *base_memory;
 
-    TRACE("surface %p, map_desc %p, rect %s, flags %#x.\n",
-            surface, map_desc, wine_dbgstr_rect(rect), flags);
+    TRACE("surface %p, map_desc %p, box %p, flags %#x.\n",
+            surface, map_desc, box, flags);
 
     if (surface->resource.map_count)
     {
@@ -3002,11 +3012,11 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
     }
 #endif /* STAGING_CSMT */
 
-    if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && rect
-            && !surface_check_block_align(surface, rect))
+    if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && box
+            && !surface_check_block_align(surface, box))
     {
-        WARN("Map rect %s is misaligned for %ux%u blocks.\n",
-                wine_dbgstr_rect(rect), format->block_width, format->block_height);
+        WARN("Map rect %p is misaligned for %ux%u blocks.\n",
+                box, format->block_width, format->block_height);
 
         if (surface->resource.pool == WINED3D_POOL_DEFAULT)
             return WINED3DERR_INVALIDCALL;
@@ -3035,16 +3045,12 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
     }
 
 #if defined(STAGING_CSMT)
-    if (rect)
+    if (box)
     {
-        surface->lockedRect = *rect;
-
-        box.left = rect->left;
-        box.top = rect->top;
-        box.front = 0;
-        box.right = rect->right;
-        box.bottom = rect->bottom;
-        box.back = 1;
+        surface->lockedRect.left = box->left;
+        surface->lockedRect.top = box->top;
+        surface->lockedRect.right = box->right;
+        surface->lockedRect.bottom = box->bottom;
     }
     else
     {
@@ -3054,7 +3060,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
         surface->lockedRect.bottom = surface->resource.height;
     }
 
-    return wined3d_resource_map(&surface->resource, map_desc, rect ? &box : NULL, flags);
+    return wined3d_resource_map(&surface->resource, map_desc, box, flags);
 }
 
 void wined3d_surface_getdc_cs(struct wined3d_surface *surface)
@@ -3096,9 +3102,30 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
 
     if (!(surface->container->resource.format_flags & WINED3DFMT_FLAG_GETDC))
     {
-        WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->container->resource.format->id));
+        WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->resource.format->id));
         return WINED3DERR_INVALIDCALL;
     }
+
+    /* Give more detailed info for ddraw. */
+    if (surface->flags & SFLAG_DCINUSE)
+        return WINEDDERR_DCALREADYCREATED;
+
+    /* Can't GetDC if the surface is locked. */
+    if (surface->resource.map_count)
+        return WINED3DERR_INVALIDCALL;
+
+    surface->flags |= SFLAG_DCINUSE;
+    surface->resource.map_count++;
+    wined3d_cs_emit_getdc(device->cs, surface);
+    *dc = surface->hDC;
+    TRACE("Returning dc %p.\n", *dc);
+
+    return *dc ? WINED3D_OK : WINED3DERR_INVALIDCALL;
+}
+
+void wined3d_surface_releasedc_cs(struct wined3d_surface *surface)
+{
+    if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
 #else  /* STAGING_CSMT */
     surface_prepare_map_memory(surface);
     if (flags & WINED3D_MAP_DISCARD)
@@ -3109,10 +3136,16 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
     }
     else
     {
+        struct wined3d_context *context = NULL;
+
         if (surface->resource.usage & WINED3DUSAGE_DYNAMIC)
             WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n");
 
-        surface_load_location(surface, surface->resource.map_binding);
+        if (surface->resource.device->d3d_initialized)
+            context = context_acquire(surface->resource.device, NULL);
+        surface_load_location(surface, context, surface->resource.map_binding);
+        if (context)
+            context_release(context);
     }
 
     if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
@@ -3152,10 +3185,10 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
     if (fmt_flags & WINED3DFMT_FLAG_BROKEN_PITCH)
         map_desc->row_pitch = surface->resource.width * format->byte_count;
     else
-        wined3d_resource_get_pitch(&surface->resource, &map_desc->row_pitch, &map_desc->slice_pitch);
-    map_desc->slice_pitch = 0;
+        map_desc->row_pitch = wined3d_surface_get_pitch(surface);
+    map_desc->slice_pitch = surface->resource.height * map_desc->row_pitch;
 
-    if (!rect)
+    if (!box)
     {
         map_desc->data = base_memory;
         surface->lockedRect.left = 0;
@@ -3170,19 +3203,19 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
             /* Compressed textures are block based, so calculate the offset of
              * the block that contains the top-left pixel of the locked rectangle. */
             map_desc->data = base_memory
-                    + ((rect->top / format->block_height) * map_desc->row_pitch)
-                    + ((rect->left / format->block_width) * format->block_byte_count);
+                    + ((box->top / format->block_height) * map_desc->row_pitch)
+                    + ((box->left / format->block_width) * format->block_byte_count);
         }
         else
         {
             map_desc->data = base_memory
-                    + (map_desc->row_pitch * rect->top)
-                    + (rect->left * format->byte_count);
+                    + (map_desc->row_pitch * box->top)
+                    + (box->left * format->byte_count);
         }
-        surface->lockedRect.left = rect->left;
-        surface->lockedRect.top = rect->top;
-        surface->lockedRect.right = rect->right;
-        surface->lockedRect.bottom = rect->bottom;
+        surface->lockedRect.left = box->left;
+        surface->lockedRect.top = box->top;
+        surface->lockedRect.right = box->right;
+        surface->lockedRect.bottom = box->bottom;
     }
 
     TRACE("Locked rect %s.\n", wine_dbgstr_rect(&surface->lockedRect));
@@ -3194,9 +3227,10 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
 HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
 {
     HRESULT hr;
+    struct wined3d_device *device = surface->resource.device;
+    struct wined3d_context *context = NULL;
 
     TRACE("surface %p, dc %p.\n", surface, dc);
-#endif /* STAGING_CSMT */
 
     /* Give more detailed info for ddraw. */
     if (surface->flags & SFLAG_DCINUSE)
@@ -3206,60 +3240,36 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
     if (surface->resource.map_count)
         return WINED3DERR_INVALIDCALL;
 
-#if defined(STAGING_CSMT)
-    surface->flags |= SFLAG_DCINUSE;
-    surface->resource.map_count++;
-    wined3d_cs_emit_getdc(device->cs, surface);
-    *dc = surface->hDC;
-    TRACE("Returning dc %p.\n", *dc);
-
-    return *dc ? WINED3D_OK : WINED3DERR_INVALIDCALL;
-}
-
-void wined3d_surface_releasedc_cs(struct wined3d_surface *surface)
-{
-    if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
-            && surface->resource.map_binding != WINED3D_LOCATION_DIB))
-    {
-        /* The game Salammbo modifies the surface contents without mapping the surface between
-         * a GetDC/ReleaseDC operation and flipping the surface. If the DIB remains the active
-         * copy and is copied to the screen, this update, which draws the mouse pointer, is lost.
-         * Do not only copy the DIB to the map location, but also make sure the map location is
-         * copied back to the DIB in the next getdc call.
-         *
-         * The same consideration applies to user memory surfaces. */
-        struct wined3d_device *device = surface->resource.device;
-        struct wined3d_context *context = NULL;
-
-        if (device->d3d_initialized)
-            context = context_acquire(device, NULL);
+    if (device->d3d_initialized)
+        context = context_acquire(surface->resource.device, NULL);
 
-        wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding);
-        wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_DIB);
-        if (context)
-            context_release(context);
-    }
-#else  /* STAGING_CSMT */
     /* Create a DIB section if there isn't a dc yet. */
     if (!surface->hDC)
     {
         if (surface->flags & SFLAG_CLIENT)
         {
-            surface_load_location(surface, WINED3D_LOCATION_SYSMEM);
+            surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM);
             surface_release_client_storage(surface);
         }
         hr = surface_create_dib_section(surface);
         if (FAILED(hr))
-            return WINED3DERR_INVALIDCALL;
+        {
+            if (context)
+                context_release(context);
+             return WINED3DERR_INVALIDCALL;
+        }
         if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
                 || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
                 || surface->pbo))
             surface->resource.map_binding = WINED3D_LOCATION_DIB;
     }
 
-    surface_load_location(surface, WINED3D_LOCATION_DIB);
+    surface_load_location(surface, context, WINED3D_LOCATION_DIB);
     surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB);
 
+    if (context)
+        context_release(context);
+
     surface->flags |= SFLAG_DCINUSE;
     surface->resource.map_count++;
 
@@ -3267,7 +3277,6 @@ void wined3d_surface_releasedc_cs(struct wined3d_surface *surface)
     TRACE("Returning dc %p.\n", *dc);
 
     return WINED3D_OK;
-#endif /* STAGING_CSMT */
 }
 
 HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc)
@@ -3287,22 +3296,9 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc)
     surface->resource.map_count--;
     surface->flags &= ~SFLAG_DCINUSE;
 
-#if defined(STAGING_CSMT)
-    wined3d_cs_emit_releasedc(surface->resource.device->cs, surface);
-
-    return WINED3D_OK;
-}
-
-static void read_from_framebuffer(struct wined3d_surface *surface,
-        struct wined3d_context *old_ctx, DWORD dst_location)
-{
-    struct wined3d_device *device = surface->resource.device;
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-    struct wined3d_surface *restore_rt;
-#else  /* STAGING_CSMT */
     if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
             || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
+#endif /* STAGING_CSMT */
             && surface->resource.map_binding != WINED3D_LOCATION_DIB))
     {
         /* The game Salammbo modifies the surface contents without mapping the surface between
@@ -3312,49 +3308,76 @@ static void read_from_framebuffer(struct wined3d_surface *surface,
          * copied back to the DIB in the next getdc call.
          *
          * The same consideration applies to user memory surfaces. */
-        surface_load_location(surface, surface->resource.map_binding);
+        struct wined3d_device *device = surface->resource.device;
+        struct wined3d_context *context = NULL;
+
+        if (device->d3d_initialized)
+            context = context_acquire(device, NULL);
+
+#if defined(STAGING_CSMT)
+        wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding);
+        wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_DIB);
+        if (context)
+            context_release(context);
+    }
+}
+
+HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc)
+{
+    TRACE("surface %p, dc %p.\n", surface, dc);
+
+    if (!(surface->flags & SFLAG_DCINUSE))
+        return WINEDDERR_NODC;
+
+    if (surface->hDC != dc)
+    {
+        WARN("Application tries to release invalid DC %p, surface DC is %p.\n",
+                dc, surface->hDC);
+        return WINEDDERR_NODC;
+    }
+
+    surface->resource.map_count--;
+    surface->flags &= ~SFLAG_DCINUSE;
+
+    wined3d_cs_emit_releasedc(surface->resource.device->cs, surface);
+#else  /* STAGING_CSMT */
+        surface_load_location(surface, context, surface->resource.map_binding);
         surface_invalidate_location(surface, WINED3D_LOCATION_DIB);
+        if (context)
+            context_release(context);
     }
+#endif /* STAGING_CSMT */
 
     return WINED3D_OK;
 }
 
-static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_location)
+static void read_from_framebuffer(struct wined3d_surface *surface,
+        struct wined3d_context *old_ctx, DWORD dst_location)
 {
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-#endif /* STAGING_CSMT */
+    struct wined3d_context *context = old_ctx;
+    struct wined3d_surface *restore_rt = NULL;
     BYTE *mem;
     BYTE *row, *top, *bottom;
     int i;
     BOOL srcIsUpsideDown;
     struct wined3d_bo_address data;
-    UINT row_pitch, slice_pitch;
-
 #if defined(STAGING_CSMT)
+    DWORD slice_pitch, pitch;
+
     wined3d_resource_get_memory(&surface->resource, dst_location, &data);
+#else  /* STAGING_CSMT */
 
-    /* Context_release does not restore the original context in case of
-     * nested context_acquire calls. Only read_from_framebuffer and
-     * surface_blt_to_drawable use nested context_acquire calls. Manually
-     * restore the original context at the end of the function if needed. */
-    if (old_ctx->current_rt == surface)
-    {
-        restore_rt = NULL;
-        context = old_ctx;
-    }
-    else
+    surface_get_memory(surface, &data, dst_location);
+#endif /* STAGING_CSMT */
+
+    if (surface != old_ctx->current_rt)
     {
         restore_rt = old_ctx->current_rt;
         context = context_acquire(device, surface);
     }
 
-#else  /* STAGING_CSMT */
-    surface_get_memory(surface, &data, dst_location);
-
-    context = context_acquire(device, surface);
-#endif /* STAGING_CSMT */
     context_apply_blit_state(context, device);
     gl_info = context->gl_info;
 
@@ -3387,8 +3410,13 @@ static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_loc
     }
 
     /* Setup pixel store pack state -- to glReadPixels into the correct place */
-    wined3d_resource_get_pitch(&surface->resource, &row_pitch, &slice_pitch);
-    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, row_pitch / surface->resource.format->byte_count);
+#if defined(STAGING_CSMT)
+    wined3d_resource_get_pitch(&surface->resource, &pitch, &slice_pitch);
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, pitch / surface->resource.format->byte_count);
+#else  /* STAGING_CSMT */
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH,
+            wined3d_surface_get_pitch(surface) / surface->resource.format->byte_count);
+#endif /* STAGING_CSMT */
     checkGLcall("glPixelStorei");
 
     gl_info->gl_ops.gl.p_glReadPixels(0, 0,
@@ -3405,10 +3433,10 @@ static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_loc
     {
         /* glReadPixels returns the image upside down, and there is no way to prevent this.
          * Flip the lines in software. */
-        UINT pitch, slice_pitch;
-
-        wined3d_resource_get_pitch(&surface->resource, &pitch, &slice_pitch);
+#if !defined(STAGING_CSMT)
+        UINT pitch = wined3d_surface_get_pitch(surface);
 
+#endif /* STAGING_CSMT */
         if (!(row = HeapAlloc(GetProcessHeap(), 0, pitch)))
             goto error;
 
@@ -3443,28 +3471,29 @@ error:
         checkGLcall("glBindBuffer");
     }
 
-#if defined(STAGING_CSMT)
     if (restore_rt)
-    {
-        context_release(context);
-        context = context_acquire(device, restore_rt);
-        context_release(context);
-    }
-#else  /* STAGING_CSMT */
-    context_release(context);
-#endif /* STAGING_CSMT */
+        context_restore(context, restore_rt);
 }
 
 /* Read the framebuffer contents into a texture. Note that this function
  * doesn't do any kind of flipping. Using this on an onscreen surface will
- * result in a flipped D3D texture. */
-void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
+ * result in a flipped D3D texture.
+ *
+ * Context activation is done by the caller. This function may temporarily
+ * switch to a different context and restore the original one before return. */
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct wined3d_context *old_ctx)
 {
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
+    struct wined3d_context *context = old_ctx;
+    struct wined3d_surface *restore_rt = NULL;
+
+    if (old_ctx->current_rt != surface)
+    {
+        restore_rt = old_ctx->current_rt;
+        context = context_acquire(device, surface);
+    }
 
-    context = context_acquire(device, surface);
     gl_info = context->gl_info;
     device_invalidate_state(device, STATE_FRAMEBUFFER);
 
@@ -3483,116 +3512,51 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
             0, 0, 0, 0, surface->resource.width, surface->resource.height);
     checkGLcall("glCopyTexSubImage2D");
 
-    context_release(context);
+    if (restore_rt)
+        context_restore(context, restore_rt);
 }
 
 void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, BOOL multisample)
 {
     if (multisample)
     {
-        if (surface->rb_multisample)
-            return;
+        DWORD samples;
 
-        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_multisample);
-        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_multisample);
-        gl_info->fbo_ops.glRenderbufferStorageMultisample(GL_RENDERBUFFER, surface->resource.multisample_type,
-                surface->resource.format->glInternal, surface->pow2Width, surface->pow2Height);
-        checkGLcall("glRenderbufferStorageMultisample()");
-        TRACE("Created multisample rb %u.\n", surface->rb_multisample);
-    }
-    else
-    {
-        if (surface->rb_resolved)
+        if (surface->rb_multisample)
             return;
 
-        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_resolved);
-        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_resolved);
-        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, surface->resource.format->glInternal,
-                surface->pow2Width, surface->pow2Height);
-        checkGLcall("glRenderbufferStorage()");
-        TRACE("Created resolved rb %u.\n", surface->rb_resolved);
-    }
-}
-
-#if !defined(STAGING_CSMT)
-void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back)
-{
-    if (front->container->level_count != 1 || front->container->layer_count != 1
-            || back->container->level_count != 1 || back->container->layer_count != 1)
-        ERR("Flip between surfaces %p and %p not supported.\n", front, back);
-
-    /* Flip the surface contents */
-    /* Flip the DC */
-    {
-        HDC tmp;
-        tmp = front->hDC;
-        front->hDC = back->hDC;
-        back->hDC = tmp;
-    }
-
-    /* Flip the DIBsection */
-    {
-        HBITMAP tmp = front->dib.DIBsection;
-        front->dib.DIBsection = back->dib.DIBsection;
-        back->dib.DIBsection = tmp;
-    }
-
-    /* Flip the surface data */
-    {
-        void* tmp;
-
-        tmp = front->dib.bitmap_data;
-        front->dib.bitmap_data = back->dib.bitmap_data;
-        back->dib.bitmap_data = tmp;
-
-        tmp = front->resource.heap_memory;
-        front->resource.heap_memory = back->resource.heap_memory;
-        back->resource.heap_memory = tmp;
-    }
-
-    /* Flip the PBO */
-    {
-        GLuint tmp_pbo = front->pbo;
-        front->pbo = back->pbo;
-        back->pbo = tmp_pbo;
-    }
-
-    /* Flip the opengl texture */
-    {
-        GLuint tmp;
-
-        tmp = back->container->texture_rgb.name;
-        back->container->texture_rgb.name = front->container->texture_rgb.name;
-        front->container->texture_rgb.name = tmp;
-
-        tmp = back->container->texture_srgb.name;
-        back->container->texture_srgb.name = front->container->texture_srgb.name;
-        front->container->texture_srgb.name = tmp;
-
-        tmp = back->rb_multisample;
-        back->rb_multisample = front->rb_multisample;
-        front->rb_multisample = tmp;
-
-        tmp = back->rb_resolved;
-        back->rb_resolved = front->rb_resolved;
-        front->rb_resolved = tmp;
+        /* TODO: Nvidia exposes their Coverage Sample Anti-Aliasing (CSAA) feature
+         * through type == MULTISAMPLE_XX and quality != 0. This could be mapped
+         * to GL_NV_framebuffer_multisample_coverage.
+         *
+         * AMD has a similar feature called Enhanced Quality Anti-Aliasing (EQAA),
+         * but it does not have an equivalent OpenGL extension. */
+        if (surface->resource.multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
+            samples = surface->resource.multisample_quality;
+        else
+            samples = surface->resource.multisample_type;
 
-        resource_unload(&back->resource);
-        resource_unload(&front->resource);
+        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_multisample);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_multisample);
+        gl_info->fbo_ops.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+                surface->resource.format->glInternal, surface->pow2Width, surface->pow2Height);
+        checkGLcall("glRenderbufferStorageMultisample()");
+        TRACE("Created multisample rb %u.\n", surface->rb_multisample);
     }
-
+    else
     {
-        DWORD tmp_flags = back->flags;
-        back->flags = front->flags;
-        front->flags = tmp_flags;
+        if (surface->rb_resolved)
+            return;
 
-        tmp_flags = back->locations;
-        back->locations = front->locations;
-        front->locations = tmp_flags;
+        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_resolved);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_resolved);
+        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, surface->resource.format->glInternal,
+                surface->pow2Width, surface->pow2Height);
+        checkGLcall("glRenderbufferStorage()");
+        TRACE("Created resolved rb %u.\n", surface->rb_resolved);
     }
 }
 
-#endif /* STAGING_CSMT */
 /* Does a direct frame buffer -> texture copy. Stretching is done with single
  * pixel copy calls. */
 static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface,
@@ -4027,7 +3991,6 @@ void surface_translate_drawable_coords(const struct wined3d_surface *surface, HW
     rect->bottom = drawable_height - rect->bottom;
 }
 
-#if defined(STAGING_CSMT)
 /* Context activation is done by the caller. */
 static void surface_blt_to_drawable(const struct wined3d_device *device,
         struct wined3d_context *old_ctx,
@@ -4036,48 +3999,27 @@ static void surface_blt_to_drawable(const struct wined3d_device *device,
         struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
 {
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-    struct wined3d_surface *restore_rt;
+    struct wined3d_context *context = old_ctx;
+    struct wined3d_surface *restore_rt = NULL;
     RECT src_rect, dst_rect;
 
     src_rect = *src_rect_in;
     dst_rect = *dst_rect_in;
 
-    /* Context_release does not restore the original context in case of
-     * nested context_acquire calls. Only read_from_framebuffer and
-     * surface_blt_to_drawable use nested context_acquire calls. Manually
-     * restore the original context at the end of the function if needed. */
-    if (old_ctx->current_rt == dst_surface)
-    {
-        restore_rt = NULL;
-        context = old_ctx;
-    }
-    else
+
+    if (old_ctx->current_rt != dst_surface)
     {
         restore_rt = old_ctx->current_rt;
         context = context_acquire(device, dst_surface);
     }
+
     gl_info = context->gl_info;
 
+#if defined(STAGING_CSMT)
     /* Make sure the surface is up-to-date. This should probably use
      * wined3d_resource_load_location() and worry about the destination
      * surface too, unless we're overwriting it completely. */
 #else  /* STAGING_CSMT */
-static void surface_blt_to_drawable(const struct wined3d_device *device,
-        enum wined3d_texture_filter_type filter, BOOL alpha_test,
-        struct wined3d_surface *src_surface, const RECT *src_rect_in,
-        struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
-{
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-    RECT src_rect, dst_rect;
-
-    src_rect = *src_rect_in;
-    dst_rect = *dst_rect_in;
-
-    context = context_acquire(device, dst_surface);
-    gl_info = context->gl_info;
-
     /* Make sure the surface is up-to-date. This should probably use
      * surface_load_location() and worry about the destination surface too,
      * unless we're overwriting it completely. */
@@ -4128,24 +4070,15 @@ static void surface_blt_to_drawable(const struct wined3d_device *device,
     if (wined3d_settings.cs_multithreaded)
         gl_info->gl_ops.gl.p_glFinish();
     else if (wined3d_settings.strict_draw_ordering
-            || (dst_surface->container->swapchain
-            && dst_surface->container->swapchain->front_buffer == dst_surface->container))
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
-
-    if (restore_rt)
-    {
-        context_release(context);
-        context = context_acquire(device, restore_rt);
-        context_release(context);
-    }
 #else  /* STAGING_CSMT */
     if (wined3d_settings.strict_draw_ordering
+#endif /* STAGING_CSMT */
             || (dst_surface->container->swapchain
             && dst_surface->container->swapchain->front_buffer == dst_surface->container))
         gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
-    context_release(context);
-#endif /* STAGING_CSMT */
+    if (restore_rt)
+        context_restore(context, restore_rt);
 }
 
 HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color)
@@ -4393,7 +4326,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
     struct wined3d_device *device = surface->resource.device;
     GLsizei w, h;
 
-    TRACE("surface %p, new location %#x.\n", surface, location);
+    TRACE("surface %p, context %p, new location %#x.\n", surface, context, location);
 
     /* TODO: Make this work for modes other than FBO */
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
@@ -4528,7 +4461,6 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
         gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
         gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
         gl_info->gl_ops.gl.p_glBindTexture(bind_target, old_binding);
 
         context_apply_fbo_state_blit(context, GL_FRAMEBUFFER,
@@ -4610,19 +4542,6 @@ static void surface_load_sysmem(struct wined3d_surface *surface,
 
     FIXME("Can't load surface %p with location flags %s into sysmem.\n",
             surface, wined3d_debug_location(surface->resource.locations));
-}
-
-/* Context activation is done by the caller. */
-static HRESULT surface_load_drawable(struct wined3d_surface *surface,
-        struct wined3d_context *context)
-{
-    RECT r;
-
-    if (surface->resource.locations & WINED3D_LOCATION_DISCARDED)
-    {
-        TRACE("Surface was discarded, nothing to do.\n");
-        return WINED3D_OK;
-    }
 #else  /* STAGING_CSMT */
     surface->locations |= location;
     surface->ds_current_size.cx = surface->resource.width;
@@ -4707,9 +4626,12 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD
     memcpy(dst.addr, src.addr, size);
 }
 
+/* Context activation is done by the caller. */
 static void surface_load_sysmem(struct wined3d_surface *surface,
-        const struct wined3d_gl_info *gl_info, DWORD dst_location)
+        struct wined3d_context *context, DWORD dst_location)
 {
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
     if (surface->locations & surface_simple_locations)
     {
         surface_copy_simple_location(surface, dst_location);
@@ -4717,42 +4639,43 @@ static void surface_load_sysmem(struct wined3d_surface *surface,
     }
 
     if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED))
-        surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB);
+        surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB);
 
     /* Download the surface to system memory. */
     if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
     {
-        struct wined3d_device *device = surface->resource.device;
-        struct wined3d_context *context;
-
-        /* TODO: Use already acquired context when possible. */
-        context = context_acquire(device, NULL);
-
         wined3d_texture_bind_and_dirtify(surface->container, context,
                 !(surface->locations & WINED3D_LOCATION_TEXTURE_RGB));
         surface_download_data(surface, gl_info, dst_location);
 
-        context_release(context);
-
         return;
     }
 
     if (surface->locations & WINED3D_LOCATION_DRAWABLE)
     {
-        read_from_framebuffer(surface, dst_location);
+        read_from_framebuffer(surface, context, dst_location);
         return;
     }
 
     FIXME("Can't load surface %p with location flags %s into sysmem.\n",
             surface, wined3d_debug_location(surface->locations));
+#endif /* STAGING_CSMT */
 }
 
+/* Context activation is done by the caller. */
 static HRESULT surface_load_drawable(struct wined3d_surface *surface,
-        const struct wined3d_gl_info *gl_info)
+        struct wined3d_context *context)
 {
     RECT r;
-#endif /* STAGING_CSMT */
 
+#if defined(STAGING_CSMT)
+    if (surface->resource.locations & WINED3D_LOCATION_DISCARDED)
+    {
+        TRACE("Surface was discarded, nothing to do.\n");
+        return WINED3D_OK;
+    }
+
+#endif /* STAGING_CSMT */
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
             && wined3d_resource_is_offscreen(&surface->container->resource))
     {
@@ -4763,6 +4686,9 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface,
     surface_get_rect(surface, NULL, &r);
 #if defined(STAGING_CSMT)
     wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB);
+#else  /* STAGING_CSMT */
+    surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB);
+#endif /* STAGING_CSMT */
     surface_blt_to_drawable(surface->resource.device, context,
             WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r);
 
@@ -4777,6 +4703,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_color_key_conversion *conversion;
     struct wined3d_texture *texture = surface->container;
+#if defined(STAGING_CSMT)
     UINT width, src_row_pitch, src_slice_pitch, dst_pitch;
     struct wined3d_bo_address data;
     struct wined3d_format format;
@@ -4797,56 +4724,14 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             && wined3d_resource_is_offscreen(&texture->resource)
             && (surface->resource.locations & WINED3D_LOCATION_DRAWABLE))
     {
-        surface_load_fb_texture(surface, srgb);
+        surface_load_fb_texture(surface, srgb, context);
 
         return WINED3D_OK;
     }
 
     if (surface->resource.locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
-            && (surface->container->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
-            && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
-                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
-                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
-    {
-        if (srgb)
-            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB,
-                    &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect);
-        else
-            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB,
-                    &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect);
-
-        return WINED3D_OK;
-    }
-
-    if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)
-            && (!srgb || (surface->container->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB))
-            && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
-                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
-                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
-    {
-        DWORD src_location = surface->resource.locations & WINED3D_LOCATION_RB_RESOLVED ?
-                WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE;
-        DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
-        RECT rect = {0, 0, surface->resource.width, surface->resource.height};
-
-        surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location,
 #else  /* STAGING_CSMT */
-    surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB);
-    surface_blt_to_drawable(surface->resource.device,
-            WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r);
-
-    return WINED3D_OK;
-}
-
-static HRESULT surface_load_texture(struct wined3d_surface *surface,
-        const struct wined3d_gl_info *gl_info, BOOL srgb)
-{
-    RECT src_rect = {0, 0, surface->resource.width, surface->resource.height};
-    struct wined3d_device *device = surface->resource.device;
-    const struct wined3d_color_key_conversion *conversion;
-    struct wined3d_texture *texture = surface->container;
-    struct wined3d_context *context;
-    UINT width, src_row_pitch, src_slice_pitch, dst_pitch;
+    UINT width, src_pitch, dst_pitch;
     struct wined3d_bo_address data;
     struct wined3d_format format;
     POINT dst_point = {0, 0};
@@ -4856,27 +4741,37 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             && wined3d_resource_is_offscreen(&texture->resource)
             && (surface->locations & WINED3D_LOCATION_DRAWABLE))
     {
-        surface_load_fb_texture(surface, srgb);
+        surface_load_fb_texture(surface, srgb, context);
 
         return WINED3D_OK;
     }
 
     if (surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
+#endif /* STAGING_CSMT */
             && (surface->container->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
             && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
                 NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
                 NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
     {
         if (srgb)
-            surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB,
+            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB,
                     &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect);
         else
-            surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB,
+            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB,
                     &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect);
 
         return WINED3D_OK;
     }
 
+#if defined(STAGING_CSMT)
+    if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)
+            && (!srgb || (surface->container->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB))
+            && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
+    {
+        DWORD src_location = surface->resource.locations & WINED3D_LOCATION_RB_RESOLVED ?
+#else  /* STAGING_CSMT */
     if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)
             && (!srgb || (surface->container->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB))
             && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
@@ -4884,12 +4779,12 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
                 NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
     {
         DWORD src_location = surface->locations & WINED3D_LOCATION_RB_RESOLVED ?
+#endif /* STAGING_CSMT */
                 WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE;
         DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
         RECT rect = {0, 0, surface->resource.width, surface->resource.height};
 
-        surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, src_location,
-#endif /* STAGING_CSMT */
+        surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location,
                 &rect, surface, dst_location, &rect);
 
         return WINED3D_OK;
@@ -4928,6 +4823,12 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         wined3d_resource_prepare_system_memory(&surface->resource);
         wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM);
     }
+
+    wined3d_texture_prepare_texture(texture, context, srgb);
+    wined3d_texture_bind_and_dirtify(texture, context, srgb);
+
+    width = surface->resource.width;
+    wined3d_resource_get_pitch(&surface->resource, &src_row_pitch, &src_slice_pitch);
 #else  /* STAGING_CSMT */
         if ((surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_RGB)
@@ -4935,7 +4836,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             /* Performance warning... */
             FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface);
             surface_prepare_map_memory(surface);
-            surface_load_location(surface, surface->resource.map_binding);
+            surface_load_location(surface, context, surface->resource.map_binding);
         }
     }
     else
@@ -4946,7 +4847,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             /* Performance warning... */
             FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface);
             surface_prepare_map_memory(surface);
-            surface_load_location(surface, surface->resource.map_binding);
+            surface_load_location(surface, context, surface->resource.map_binding);
         }
     }
 
@@ -4955,18 +4856,15 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         WARN("Trying to load a texture from sysmem, but no simple location is valid.\n");
         /* Lets hope we get it from somewhere... */
         surface_prepare_system_memory(surface);
-        surface_load_location(surface, WINED3D_LOCATION_SYSMEM);
+        surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM);
     }
 
-    /* TODO: Use already acquired context when possible. */
-    context = context_acquire(device, NULL);
-#endif /* STAGING_CSMT */
-
     wined3d_texture_prepare_texture(texture, context, srgb);
     wined3d_texture_bind_and_dirtify(texture, context, srgb);
 
     width = surface->resource.width;
-    wined3d_resource_get_pitch(&surface->resource, &src_row_pitch, &src_slice_pitch);
+    src_pitch = wined3d_surface_get_pitch(surface);
+#endif /* STAGING_CSMT */
 
     format = *texture->resource.format;
     if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
@@ -4998,7 +4896,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &data);
 #else  /* STAGING_CSMT */
         surface_prepare_map_memory(surface);
-        surface_load_location(surface, surface->resource.map_binding);
+        surface_load_location(surface, context, surface->resource.map_binding);
         surface_remove_pbo(surface, gl_info);
     }
 
@@ -5018,9 +4916,15 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
             context_release(context);
             return E_OUTOFMEMORY;
         }
+#if defined(STAGING_CSMT)
         format.convert(data.addr, mem, src_row_pitch, src_row_pitch * height,
                 dst_pitch, dst_pitch * height, width, height, 1);
         src_row_pitch = dst_pitch;
+#else  /* STAGING_CSMT */
+        format.convert(data.addr, mem, src_pitch, src_pitch * height,
+                dst_pitch, dst_pitch * height, width, height, 1);
+        src_pitch = dst_pitch;
+#endif /* STAGING_CSMT */
         data.addr = mem;
     }
     else if (conversion)
@@ -5040,6 +4944,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         }
         if (texture->swapchain && texture->swapchain->palette)
             palette = texture->swapchain->palette;
+#if defined(STAGING_CSMT)
         conversion->convert(data.addr, src_row_pitch, mem, dst_pitch,
                 width, height, palette, &texture->async.gl_color_key);
         src_row_pitch = dst_pitch;
@@ -5048,8 +4953,17 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
 
     wined3d_surface_upload_data(surface, gl_info, &format, &src_rect,
             src_row_pitch, &dst_point, srgb, wined3d_const_bo_address(&data));
+#else  /* STAGING_CSMT */
+        conversion->convert(data.addr, src_pitch, mem, dst_pitch,
+                width, height, palette, &texture->async.gl_color_key);
+        src_pitch = dst_pitch;
+        data.addr = mem;
+    }
+
+    wined3d_surface_upload_data(surface, gl_info, &format, &src_rect,
+            src_pitch, &dst_point, srgb, wined3d_const_bo_address(&data));
+#endif /* STAGING_CSMT */
 
-#if defined(STAGING_CSMT)
     HeapFree(GetProcessHeap(), 0, mem);
 
     return WINED3D_OK;
@@ -5060,7 +4974,11 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct
 {
     RECT rect = {0, 0, surface->resource.width, surface->resource.height};
 
+#if defined(STAGING_CSMT)
     if (!(surface->resource.locations & WINED3D_LOCATION_RB_MULTISAMPLE))
+#else  /* STAGING_CSMT */
+    if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE))
+#endif /* STAGING_CSMT */
         ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n",
                 surface);
 
@@ -5068,35 +4986,16 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct
             surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect);
 }
 
+#if defined(STAGING_CSMT)
 /* Context activation is done by the caller. */
 static void wined3d_surface_load_location(struct wined3d_resource *resource,
         struct wined3d_context *context, DWORD location)
 {
     struct wined3d_surface *surface = surface_from_resource(resource);
 #else  /* STAGING_CSMT */
-    context_release(context);
-
-    HeapFree(GetProcessHeap(), 0, mem);
-
-    return WINED3D_OK;
-}
-
-static void surface_multisample_resolve(struct wined3d_surface *surface)
-{
-    RECT rect = {0, 0, surface->resource.width, surface->resource.height};
-
-    if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE))
-        ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n",
-                surface);
-
-    surface_blt_fbo(surface->resource.device, WINED3D_TEXF_POINT,
-            surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect);
-}
-
-HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location)
+/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */
+HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location)
 {
-    struct wined3d_device *device = surface->resource.device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
 #endif /* STAGING_CSMT */
     HRESULT hr;
 
@@ -5133,9 +5032,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location)
 #else  /* STAGING_CSMT */
                 && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED))
         {
-            struct wined3d_context *context = context_acquire(device, NULL);
             surface_load_ds_location(surface, context, location);
-            context_release(context);
             return WINED3D_OK;
         }
         else if (location & surface->locations
@@ -5180,13 +5077,16 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location)
         case WINED3D_LOCATION_USER_MEMORY:
         case WINED3D_LOCATION_SYSMEM:
         case WINED3D_LOCATION_BUFFER:
-#if defined(STAGING_CSMT)
             surface_load_sysmem(surface, context, location);
             break;
 
         case WINED3D_LOCATION_DRAWABLE:
             if (FAILED(hr = surface_load_drawable(surface, context)))
+#if defined(STAGING_CSMT)
                 return;
+#else  /* STAGING_CSMT */
+                return hr;
+#endif /* STAGING_CSMT */
             break;
 
         case WINED3D_LOCATION_RB_RESOLVED:
@@ -5197,23 +5097,9 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location)
         case WINED3D_LOCATION_TEXTURE_SRGB:
             if (FAILED(hr = surface_load_texture(surface, context,
                     location == WINED3D_LOCATION_TEXTURE_SRGB)))
+#if defined(STAGING_CSMT)
                 return;
 #else  /* STAGING_CSMT */
-            surface_load_sysmem(surface, gl_info, location);
-            break;
-
-        case WINED3D_LOCATION_DRAWABLE:
-            if (FAILED(hr = surface_load_drawable(surface, gl_info)))
-                return hr;
-            break;
-
-        case WINED3D_LOCATION_RB_RESOLVED:
-            surface_multisample_resolve(surface);
-            break;
-
-        case WINED3D_LOCATION_TEXTURE_RGB:
-        case WINED3D_LOCATION_TEXTURE_SRGB:
-            if (FAILED(hr = surface_load_texture(surface, gl_info, location == WINED3D_LOCATION_TEXTURE_SRGB)))
                 return hr;
 #endif /* STAGING_CSMT */
             break;
@@ -5428,11 +5314,11 @@ static void ffp_blit_blit_surface(struct wined3d_device *device, DWORD filter,
         struct wined3d_surface *dst_surface, const RECT *dst_rect,
         const struct wined3d_color_key *color_key)
 {
+    struct wined3d_context *context;
+
     /* Blit from offscreen surface to render target */
     struct wined3d_color_key old_blt_key = src_surface->container->async.src_blt_color_key;
     DWORD old_color_key_flags = src_surface->container->async.color_key_flags;
-#if defined(STAGING_CSMT)
-    struct wined3d_context *context;
 
     TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
 
@@ -5447,21 +5333,10 @@ static void ffp_blit_blit_surface(struct wined3d_device *device, DWORD filter,
     wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT,
             (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
 
+#if defined(STAGING_CSMT)
     wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding);
     wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding);
 #else  /* STAGING_CSMT */
-
-    TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
-
-    wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT, color_key);
-
-    surface_blt_to_drawable(device, filter,
-            !!color_key, src_surface, src_rect, dst_surface, dst_rect);
-
-    /* Restore the color key parameters */
-    wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT,
-            (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
-
     surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding);
     surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding);
 #endif /* STAGING_CSMT */
@@ -5620,11 +5495,11 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *
         struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
         const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
 {
+#if defined(STAGING_CSMT)
     int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
     const struct wined3d_format *src_format, *dst_format;
     unsigned int src_fmt_flags, dst_fmt_flags;
     struct wined3d_texture *src_texture = NULL;
-#if defined(STAGING_CSMT)
     void *src_data = NULL, *dst_data = NULL;
     UINT src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch;
     const BYTE *sbase = NULL;
@@ -5656,6 +5531,11 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *
         src_data = dst_data;
         src_row_pitch = dst_row_pitch;
 #else  /* STAGING_CSMT */
+    const struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1};
+    int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
+    const struct wined3d_format *src_format, *dst_format;
+    unsigned int src_fmt_flags, dst_fmt_flags;
+    struct wined3d_texture *src_texture = NULL;
     struct wined3d_map_desc dst_map, src_map;
     const BYTE *sbase = NULL;
     HRESULT hr = WINED3D_OK;
@@ -5721,7 +5601,7 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *
         wined3d_resource_get_pitch(&dst_surface->resource, &dst_row_pitch, &dst_slice_pitch);
         dst_data = wined3d_resource_get_map_ptr(&dst_surface->resource, context, 0);
 #else  /* STAGING_CSMT */
-        wined3d_surface_map(dst_surface, &dst_map, dst_rect, 0);
+        wined3d_surface_map(dst_surface, &dst_map, &dst_box, 0);
 #endif /* STAGING_CSMT */
     }
 
@@ -5770,14 +5650,14 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *
             goto release;
         }
 
-        if (!surface_check_block_align(src_surface, src_rect))
+        if (!surface_check_block_align_rect(src_surface, src_rect))
         {
             WARN("Source rectangle not block-aligned.\n");
             hr = WINED3DERR_INVALIDCALL;
             goto release;
         }
 
-        if (!surface_check_block_align(dst_surface, dst_rect))
+        if (!surface_check_block_align_rect(dst_surface, dst_rect))
         {
             WARN("Destination rectangle not block-aligned.\n");
             hr = WINED3DERR_INVALIDCALL;
@@ -6344,7 +6224,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
             | WINEDDBLT_DONOTWAIT;
 
 #if !defined(STAGING_CSMT)
-    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
+    TRACE("dst_surface %p, dst_rect_in %s, src_surface %p, src_rect_in %s, flags %#x, fx %p, filter %s.\n",
             dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in),
             flags, fx, debug_d3dtexturefiltertype(filter));
     TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage));
@@ -6633,7 +6513,11 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
                     if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect)))
                     {
                         if (!wined3d_resource_is_offscreen(&dst_surface->container->resource))
-                            surface_load_location(dst_surface, dst_surface->container->resource.draw_binding);
+                        {
+                            struct wined3d_context *context = context_acquire(device, dst_surface);
+                            surface_load_location(dst_surface, context, dst_surface->container->resource.draw_binding);
+                            context_release(context);
+                        }
                         return WINED3D_OK;
 #endif /* STAGING_CSMT */
                     }
@@ -6718,7 +6602,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
     struct wined3d_device *device = dst_surface->resource.device;
     RECT src_rect, dst_rect;
 
-    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
+    TRACE("dst_surface %p, dst_rect_in %s, src_surface %p, src_rect_in %s, flags %#x, fx %p, filter %s.\n",
             dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in),
             flags, fx, debug_d3dtexturefiltertype(filter));
     TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage));
@@ -6801,8 +6685,10 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
             return WINEDDERR_INVALIDRECT;
         }
 
-        dst_ds_flags = dst_surface->container->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
-        src_ds_flags = src_surface->container->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+        dst_ds_flags = dst_surface->container->resource.format_flags
+                & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+        src_ds_flags = src_surface->container->resource.format_flags
+                & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
         if (src_ds_flags != dst_ds_flags)
         {
             WARN("Rejecting depth / stencil blit between incompatible formats.\n");
@@ -6815,6 +6701,14 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
         memset(&src_rect, 0, sizeof(src_rect));
     }
 
+    /* FIXME: We should select the blitter in the main thread, that way we can return an error if the blit
+     * is unsupported without duplicating all the checks... */
+    if (flags & WINEDDBLT_COLORFILL && (dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS))
+    {
+        WARN("Block color fill, returning WINED3DERR_INVALIDCALL\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
     if (!fx || !(fx->dwDDFX))
         flags &= ~WINEDDBLT_DDFX;
 
@@ -6852,6 +6746,8 @@ static const struct wined3d_resource_ops surface_resource_ops =
     surface_resource_incref,
     surface_resource_decref,
     surface_unload,
+    surface_resource_sub_resource_map,
+    surface_resource_sub_resource_unmap,
     wined3d_surface_location_invalidated,
     wined3d_surface_load_location,
 };
@@ -6863,11 +6759,15 @@ static const struct wined3d_resource_ops surface_resource_ops =
                     &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
                     &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
             {
+                struct wined3d_context *context;
                 TRACE("Using FBO blit.\n");
 
-                surface_blt_fbo(device, filter,
+                context = context_acquire(device, NULL);
+                surface_blt_fbo(device, context, filter,
                         src_surface, src_surface->container->resource.draw_binding, &src_rect,
                         dst_surface, dst_surface->container->resource.draw_binding, &dst_rect);
+                context_release(context);
+
                 surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding);
                 surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding);
 
@@ -6910,12 +6810,6 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text
     unsigned int resource_size;
     HRESULT hr;
 
-    if (multisample_quality > 0)
-    {
-        FIXME("multisample_quality set to %u, substituting 0.\n", multisample_quality);
-        multisample_quality = 0;
-    }
-
     /* Quick lockable sanity check.
      * TODO: remove this after surfaces, usage and lockability have been debugged properly
      * this function is too deep to need to care about things like this.
@@ -7044,7 +6938,7 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w
     }
 
     if (FAILED(hr = device_parent->ops->surface_created(device_parent,
-            wined3d_texture_get_parent(container), object, &parent, &parent_ops)))
+            container, layer * container->level_count + level, object, &parent, &parent_ops)))
     {
         WARN("Failed to create surface parent, hr %#x.\n", hr);
         wined3d_surface_destroy(object);
index bfa6b68..cea36b8 100644 (file)
@@ -159,13 +159,19 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
 }
 
 HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain,
-        struct wined3d_surface *dst_surface)
+        struct wined3d_texture *dst_texture, unsigned int sub_resource_idx)
 {
-    struct wined3d_surface *src_surface;
+    struct wined3d_surface *src_surface, *dst_surface;
+    struct wined3d_resource *sub_resource;
     RECT src_rect, dst_rect;
 
-    TRACE("swapchain %p, dst_surface %p.\n", swapchain, dst_surface);
+    TRACE("swapchain %p, dst_texture %p, sub_resource_idx %u.\n", swapchain, dst_texture, sub_resource_idx);
 
+    if (!(sub_resource = wined3d_texture_get_sub_resource(dst_texture, sub_resource_idx)) ||
+            sub_resource->type != WINED3D_RTYPE_SURFACE)
+        return WINED3DERR_INVALIDCALL;
+
+    dst_surface = surface_from_resource(sub_resource);
     src_surface = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
     SetRect(&src_rect, 0, 0, src_surface->resource.width, src_surface->resource.height);
     dst_rect = src_rect;
@@ -180,11 +186,11 @@ HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapc
     return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
 }
 
-struct wined3d_surface * CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
-        UINT back_buffer_idx, enum wined3d_backbuffer_type type)
+struct wined3d_texture * CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
+        UINT back_buffer_idx)
 {
-    TRACE("swapchain %p, back_buffer_idx %u, type %#x.\n",
-            swapchain, back_buffer_idx, type);
+    TRACE("swapchain %p, back_buffer_idx %u.\n",
+            swapchain, back_buffer_idx);
 
     /* Return invalid if there is no backbuffer array, otherwise it will
      * crash when ddraw is used (there swapchain->back_buffers is always
@@ -201,7 +207,7 @@ struct wined3d_surface * CDECL wined3d_swapchain_get_back_buffer(const struct wi
 
     TRACE("Returning back buffer %p.\n", swapchain->back_buffers[back_buffer_idx]);
 
-    return surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[back_buffer_idx], 0));
+    return swapchain->back_buffers[back_buffer_idx];
 }
 
 HRESULT CDECL wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
@@ -315,7 +321,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
 #if defined(STAGING_CSMT)
             wined3d_resource_load_location(&backbuffer->resource, context, location);
 #else  /* STAGING_CSMT */
-            surface_load_location(backbuffer, location);
+            surface_load_location(backbuffer, context, location);
 #endif /* STAGING_CSMT */
         }
 
@@ -538,14 +544,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
     {
         wined3d_resource_load_location(&back_buffer->resource, context, back_buffer->container->resource.draw_binding);
 #else  /* STAGING_CSMT */
-        surface_load_location(back_buffer, WINED3D_LOCATION_TEXTURE_RGB);
+        surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB);
         surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE);
         swapchain->render_to_fbo = TRUE;
         swapchain_update_draw_bindings(swapchain);
     }
     else
     {
-        surface_load_location(back_buffer, back_buffer->container->resource.draw_binding);
+        surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding);
 #endif /* STAGING_CSMT */
     }
 
@@ -588,6 +594,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
     }
 
     front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
+
 #if defined(STAGING_CSMT)
     wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE);
     wined3d_resource_invalidate_location(&front->resource, ~WINED3D_LOCATION_DRAWABLE);
@@ -615,48 +622,18 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
                     depth_stencil->resource.width, depth_stencil->resource.height);
             if (depth_stencil == swapchain->device->cs->onscreen_depth_stencil)
             {
-                wined3d_surface_decref(swapchain->device->cs->onscreen_depth_stencil);
+                wined3d_texture_decref(swapchain->device->cs->onscreen_depth_stencil->container);
                 swapchain->device->cs->onscreen_depth_stencil = NULL;
 #else  /* STAGING_CSMT */
-    if (!swapchain->render_to_fbo && ((front->locations & WINED3D_LOCATION_SYSMEM)
-            || (back_buffer->locations & WINED3D_LOCATION_SYSMEM)))
-    {
-        /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying
-         * Doesn't work with render_to_fbo because we're not flipping
-         */
-
-        if (front->resource.size == back_buffer->resource.size)
-        {
-            flip_surface(front, back_buffer);
-
-            /* Tell the front buffer surface that is has been modified. However,
-             * the other locations were preserved during that, so keep the flags.
-             * This serves to update the emulated overlay, if any. */
-            surface_validate_location(front, WINED3D_LOCATION_DRAWABLE);
-        }
-        else
-        {
-            surface_validate_location(front, WINED3D_LOCATION_DRAWABLE);
-            surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE);
-            surface_validate_location(back_buffer, WINED3D_LOCATION_DRAWABLE);
-            surface_invalidate_location(back_buffer, ~WINED3D_LOCATION_DRAWABLE);
-        }
-    }
-    else
-    {
-        surface_validate_location(front, WINED3D_LOCATION_DRAWABLE);
-        surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE);
-        /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
-         * and INTEXTURE copies can keep their old content if they have any defined content.
-         * If the swapeffect is COPY, the content remains the same. If it is FLIP however,
-         * the texture / sysmem copy needs to be reloaded from the drawable
-         */
-        if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
-        {
-            surface_validate_location(back_buffer, back_buffer->container->resource.draw_binding);
-            surface_invalidate_location(back_buffer, ~back_buffer->container->resource.draw_binding);
-        }
-    }
+    surface_validate_location(front, WINED3D_LOCATION_DRAWABLE);
+    surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE);
+    /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
+     * and INTEXTURE copies can keep their old content if they have any defined content.
+     * If the swapeffect is COPY, the content remains the same.
+     *
+     * The FLIP swap effect is not implemented yet. We could mark WINED3D_LOCATION_DRAWABLE
+     * up to date and hope WGL flipped front and back buffers and read this data into
+     * the FBO. Don't bother about this for now. */
 
     if (fb->depth_stencil)
     {
@@ -669,7 +646,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
                     fb->depth_stencil->width, fb->depth_stencil->height);
             if (ds == swapchain->device->onscreen_depth_stencil)
             {
-                wined3d_surface_decref(swapchain->device->onscreen_depth_stencil);
+                wined3d_texture_decref(swapchain->device->onscreen_depth_stencil->container);
                 swapchain->device->onscreen_depth_stencil = NULL;
 #endif /* STAGING_CSMT */
             }
@@ -707,7 +684,7 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r
 #if defined(STAGING_CSMT)
     wined3d_resource_load_location(&front->resource, NULL, WINED3D_LOCATION_DIB);
 #else  /* STAGING_CSMT */
-    surface_load_location(front, WINED3D_LOCATION_DIB);
+    surface_load_location(front, NULL, WINED3D_LOCATION_DIB);
 #endif /* STAGING_CSMT */
 
     src_dc = front->hDC;
@@ -810,7 +787,7 @@ static const struct wined3d_swapchain_ops swapchain_gdi_ops =
     swapchain_gdi_present,
 };
 
-void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain)
+static void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain)
 {
     RECT client_rect;
 
@@ -916,7 +893,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_adapter *adapter = device->adapter;
-    struct wined3d_resource_desc surface_desc;
+    struct wined3d_resource_desc texture_desc;
     struct wined3d_surface *front_buffer;
     BOOL displaymode_set = FALSE;
     RECT client_rect;
@@ -924,13 +901,6 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
     HRESULT hr;
     UINT i;
 
-    if (desc->backbuffer_count > WINED3DPRESENT_BACK_BUFFER_MAX)
-    {
-        FIXME("The application requested %u back buffers, this is not supported.\n",
-                desc->backbuffer_count);
-        return WINED3DERR_INVALIDCALL;
-    }
-
     if (desc->backbuffer_count > 1)
     {
         FIXME("The application requested more than one back buffer, this is not properly supported.\n"
@@ -987,26 +957,26 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
 
     TRACE("Creating front buffer.\n");
 
-    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
-    surface_desc.format = swapchain->desc.backbuffer_format;
-    surface_desc.multisample_type = swapchain->desc.multisample_type;
-    surface_desc.multisample_quality = swapchain->desc.multisample_quality;
-    surface_desc.usage = 0;
-    surface_desc.pool = WINED3D_POOL_DEFAULT;
-    surface_desc.width = swapchain->desc.backbuffer_width;
-    surface_desc.height = swapchain->desc.backbuffer_height;
-    surface_desc.depth = 1;
-    surface_desc.size = 0;
-
-    if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-            parent, &surface_desc, &front_buffer)))
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    texture_desc.format = swapchain->desc.backbuffer_format;
+    texture_desc.multisample_type = swapchain->desc.multisample_type;
+    texture_desc.multisample_quality = swapchain->desc.multisample_quality;
+    texture_desc.usage = 0;
+    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,
+            parent, &texture_desc, &swapchain->front_buffer)))
     {
         WARN("Failed to create front buffer, hr %#x.\n", hr);
         goto err;
     }
 
-    swapchain->front_buffer = front_buffer->container;
     wined3d_texture_set_swapchain(swapchain->front_buffer, swapchain);
+    front_buffer = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
     if (!(device->wined3d->flags & WINED3D_NO3D))
     {
 #if defined(STAGING_CSMT)
@@ -1114,20 +1084,17 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
             goto err;
         }
 
-        surface_desc.usage |= WINED3DUSAGE_RENDERTARGET;
+        texture_desc.usage |= WINED3DUSAGE_RENDERTARGET;
         for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
         {
-            struct wined3d_surface *back_buffer;
-
             TRACE("Creating back buffer %u.\n", i);
-            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-                    parent, &surface_desc, &back_buffer)))
+            if (FAILED(hr = device->device_parent->ops->create_swapchain_texture(device->device_parent,
+                    parent, &texture_desc, &swapchain->back_buffers[i])))
             {
                 WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
                 swapchain->desc.backbuffer_count = i;
                 goto err;
             }
-            swapchain->back_buffers[i] = back_buffer->container;
             wined3d_texture_set_swapchain(swapchain->back_buffers[i], swapchain);
         }
     }
@@ -1138,21 +1105,26 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         TRACE("Creating depth/stencil buffer.\n");
         if (!device->auto_depth_stencil_view)
         {
-            struct wined3d_surface *ds;
+            struct wined3d_texture *ds;
+            struct wined3d_rendertarget_view_desc desc;
 
-            surface_desc.format = swapchain->desc.auto_depth_stencil_format;
-            surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+            texture_desc.format = swapchain->desc.auto_depth_stencil_format;
+            texture_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
 
-            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-                    device->device_parent, &surface_desc, &ds)))
+            if (FAILED(hr = device->device_parent->ops->create_swapchain_texture(device->device_parent,
+                    device->device_parent, &texture_desc, &ds)))
             {
                 WARN("Failed to create the auto depth/stencil surface, hr %#x.\n", hr);
                 goto err;
             }
 
-            hr = wined3d_rendertarget_view_create_from_surface(ds,
-                    NULL, &wined3d_null_parent_ops, &device->auto_depth_stencil_view);
-            wined3d_surface_decref(ds);
+            desc.format_id = ds->resource.format->id;
+            desc.u.texture.level_idx = 0;
+            desc.u.texture.layer_idx = 0;
+            desc.u.texture.layer_count = 1;
+            hr = wined3d_rendertarget_view_create(&desc, &ds->resource, NULL, &wined3d_null_parent_ops,
+                    &device->auto_depth_stencil_view);
+            wined3d_texture_decref(ds);
             if (FAILED(hr))
             {
                 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
@@ -1379,3 +1351,95 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
 
     device->filter_messages = filter_messages;
 }
+
+HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
+        unsigned int width, unsigned int height, enum wined3d_format_id format_id,
+        enum wined3d_multisample_type multisample_type, unsigned int multisample_quality)
+{
+    BOOL update_desc = FALSE;
+
+    TRACE("swapchain %p, buffer_count %u, width %u, height %u, format %s, "
+            "multisample_type %#x, multisample_quality %#x.\n",
+            swapchain, buffer_count, width, height, debug_d3dformat(format_id),
+            multisample_type, multisample_quality);
+
+    if (buffer_count && buffer_count != swapchain->desc.backbuffer_count)
+        FIXME("Cannot change the back buffer count yet.\n");
+
+    if (!width || !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 (!width)
+            width = client_rect.right;
+
+        if (!height)
+            height = client_rect.bottom;
+    }
+
+    if (width != swapchain->desc.backbuffer_width
+            || height != swapchain->desc.backbuffer_height)
+    {
+        swapchain->desc.backbuffer_width = width;
+        swapchain->desc.backbuffer_height = height;
+        update_desc = TRUE;
+    }
+
+    if (format_id == WINED3DFMT_UNKNOWN)
+    {
+        if (!swapchain->desc.windowed)
+            return WINED3DERR_INVALIDCALL;
+        format_id = swapchain->original_mode.format_id;
+    }
+
+    if (format_id != swapchain->desc.backbuffer_format)
+    {
+        swapchain->desc.backbuffer_format = format_id;
+        update_desc = TRUE;
+    }
+
+    if (multisample_type != swapchain->desc.multisample_type
+            || multisample_quality != swapchain->desc.multisample_quality)
+    {
+        swapchain->desc.multisample_type = multisample_type;
+        swapchain->desc.multisample_quality = multisample_quality;
+        update_desc = TRUE;
+    }
+
+    if (update_desc)
+    {
+        HRESULT hr;
+        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;
+        }
+    }
+
+    swapchain_update_render_to_fbo(swapchain);
+    swapchain_update_draw_bindings(swapchain);
+
+    return WINED3D_OK;
+}
index f9072ef..6091076 100644 (file)
@@ -275,6 +275,12 @@ void wined3d_texture_bind(struct wined3d_texture *texture,
         gl_tex->sampler_desc.min_filter = WINED3D_TEXF_POINT;
         gl_tex->sampler_desc.mip_filter = WINED3D_TEXF_NONE;
     }
+
+    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] && gl_info->supported[ARB_DEPTH_TEXTURE])
+    {
+        gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
+        checkGLcall("glTexParameteri(GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY)");
+    }
 }
 
 /* Context activation is done by the caller. */
@@ -295,6 +301,9 @@ void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture,
     active_sampler = context->rev_tex_unit_map[context->active_texture];
     if (active_sampler != WINED3D_UNMAPPED_STAGE)
         context_invalidate_state(context, STATE_SAMPLER(active_sampler));
+    /* FIXME: Ideally we'd only do this when touching a binding that's used by
+     * a shader. */
+    context_invalidate_state(context, STATE_SHADER_RESOURCE_BINDING);
 
     wined3d_texture_bind(texture, context, srgb);
 }
@@ -381,14 +390,9 @@ void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture,
     if (!sampler_desc->compare != !gl_tex->sampler_desc.compare)
     {
         if (sampler_desc->compare)
-        {
-            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
             gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-        }
         else
-        {
             gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-        }
         gl_tex->sampler_desc.compare = sampler_desc->compare;
     }
 
@@ -469,7 +473,7 @@ void wined3d_texture_load(struct wined3d_texture *texture,
     DWORD flag;
     UINT i;
 
-    TRACE("texture %p, srgb %#x.\n", texture, srgb);
+    TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
 
     if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
         srgb = FALSE;
@@ -610,8 +614,8 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
         DWORD flags, const struct wined3d_color_key *color_key)
 {
     struct wined3d_device *device = texture->resource.device;
-    static const DWORD all_flags = WINED3D_CKEY_COLORSPACE | WINED3D_CKEY_DST_BLT
-            | WINED3D_CKEY_DST_OVERLAY | WINED3D_CKEY_SRC_BLT | WINED3D_CKEY_SRC_OVERLAY;
+    static const DWORD all_flags = WINED3D_CKEY_DST_BLT | WINED3D_CKEY_DST_OVERLAY
+            | WINED3D_CKEY_SRC_BLT | WINED3D_CKEY_SRC_OVERLAY;
 
     TRACE("texture %p, flags %#x, color_key %p.\n", texture, flags, color_key);
 
@@ -621,22 +625,6 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (flags & WINED3D_CKEY_COLORSPACE)
-    {
-        FIXME("Unhandled flags %#x.\n", flags);
-        return WINED3DERR_INVALIDCALL;
-    }
-
-#if defined(STAGING_CSMT)
-    /*
-    if (wined3d_settings.cs_multithreaded)
-    {
-        FIXME("waiting for cs\n");
-        texture->resource.device->cs->ops->finish(texture->resource.device->cs);
-    }
-    */
-
-#endif /* STAGING_CSMT */
     wined3d_cs_emit_set_color_key(device->cs, texture, flags, color_key);
 
     return WINED3D_OK;
@@ -787,12 +775,22 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
     return WINED3D_OK;
 }
 
-static void wined3d_texture_upload_data(struct wined3d_texture *texture, const struct wined3d_sub_resource_data *data)
+static HRESULT wined3d_texture_upload_data(struct wined3d_texture *texture,
+        const struct wined3d_sub_resource_data *data)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
     struct wined3d_context *context;
     unsigned int i;
 
+    for (i = 0; i < sub_count; ++i)
+    {
+        if (!data[i].data)
+        {
+            WARN("Invalid sub-resource data specified for sub-resource %u.\n", i);
+            return E_INVALIDARG;
+        }
+    }
+
     context = context_acquire(texture->resource.device, NULL);
 
     wined3d_texture_prepare_texture(texture, context, FALSE);
@@ -808,12 +806,13 @@ static void wined3d_texture_upload_data(struct wined3d_texture *texture, const s
     }
 
     context_release(context);
+
+    return WINED3D_OK;
 }
 
 static void texture2d_sub_resource_load(struct wined3d_resource *sub_resource,
         struct wined3d_context *context, BOOL srgb)
 {
-#if defined(STAGING_CSMT)
     surface_load(surface_from_resource(sub_resource), context, srgb);
 }
 
@@ -823,22 +822,17 @@ static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub
     struct wined3d_surface *surface = surface_from_resource(sub_resource);
     struct wined3d_context *context;
 
+#if defined(STAGING_CSMT)
     context = context_acquire(surface->resource.device, NULL);
     wined3d_resource_prepare_map_memory(&surface->resource, context);
     wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding);
     context_release(context);
     wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding);
 #else  /* STAGING_CSMT */
-    surface_load(surface_from_resource(sub_resource), srgb);
-}
-
-static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
-        const struct wined3d_box *dirty_region)
-{
-    struct wined3d_surface *surface = surface_from_resource(sub_resource);
-
     surface_prepare_map_memory(surface);
-    surface_load_location(surface, surface->resource.map_binding);
+    context = context_acquire(surface->resource.device, NULL);
+    surface_load_location(surface, context, surface->resource.map_binding);
+    context_release(context);
     surface_invalidate_location(surface, ~surface->resource.map_binding);
 #endif /* STAGING_CSMT */
 }
@@ -903,7 +897,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi
     GLenum internal;
     UINT i;
 
-    TRACE("texture %p, format %s.\n", texture, debug_d3dformat(format->id));
+    TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id));
 
     if (format->convert)
     {
@@ -1047,6 +1041,27 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
     wined3d_texture_unload_gl_texture(texture);
 }
 
+static HRESULT texture2d_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_resource *sub_resource;
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), sub_resource_idx)))
+        return E_INVALIDARG;
+
+    return wined3d_surface_map(surface_from_resource(sub_resource), map_desc, box, flags);
+}
+
+static HRESULT texture2d_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    struct wined3d_resource *sub_resource;
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), sub_resource_idx)))
+        return E_INVALIDARG;
+
+    return wined3d_surface_unmap(surface_from_resource(sub_resource));
+}
+
 #if defined(STAGING_CSMT)
 static void wined3d_texture_load_location_invalidated(struct wined3d_resource *resource, DWORD location)
 {
@@ -1060,19 +1075,17 @@ static void wined3d_texture_load_location(struct wined3d_resource *resource,
     ERR("Should not be called on textures.\n");
 }
 
-static const struct wined3d_resource_ops texture_resource_ops =
+#endif /* STAGING_CSMT */
+static const struct wined3d_resource_ops texture2d_resource_ops =
 {
     texture_resource_incref,
     texture_resource_decref,
     wined3d_texture_unload,
+    texture2d_resource_sub_resource_map,
+    texture2d_resource_sub_resource_unmap,
+#if defined(STAGING_CSMT)
     wined3d_texture_load_location_invalidated,
     wined3d_texture_load_location,
-#else  /* STAGING_CSMT */
-static const struct wined3d_resource_ops texture_resource_ops =
-{
-    texture_resource_incref,
-    texture_resource_decref,
-    wined3d_texture_unload,
 #endif /* STAGING_CSMT */
 };
 
@@ -1148,7 +1161,7 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi
     }
 
     if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels, desc,
-            surface_flags, device, parent, parent_ops, &texture_resource_ops)))
+            surface_flags, device, parent, parent_ops, &texture2d_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x\n", hr);
 #if defined(STAGING_CSMT)
@@ -1286,7 +1299,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     }
 
     if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels, desc,
-            surface_flags, device, parent, parent_ops, &texture_resource_ops)))
+            surface_flags, device, parent, parent_ops, &texture2d_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
 #if defined(STAGING_CSMT)
@@ -1405,7 +1418,11 @@ static void texture3d_sub_resource_upload_data(struct wined3d_resource *sub_reso
     struct wined3d_const_bo_address addr;
     unsigned int row_pitch, slice_pitch;
 
+#if defined(STAGING_CSMT)
     wined3d_resource_get_pitch(sub_resource, &row_pitch, &slice_pitch);
+#else  /* STAGING_CSMT */
+    wined3d_volume_get_pitch(volume, &row_pitch, &slice_pitch);
+#endif /* STAGING_CSMT */
     if (row_pitch != data->row_pitch || slice_pitch != data->slice_pitch)
         FIXME("Ignoring row/slice pitch (%u/%u).\n", data->row_pitch, data->slice_pitch);
 
@@ -1468,6 +1485,36 @@ static const struct wined3d_texture_ops texture3d_ops =
     texture3d_prepare_texture,
 };
 
+static HRESULT texture3d_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_resource *sub_resource;
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), sub_resource_idx)))
+        return E_INVALIDARG;
+
+    return wined3d_volume_map(volume_from_resource(sub_resource), map_desc, box, flags);
+}
+
+static HRESULT texture3d_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    struct wined3d_resource *sub_resource;
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), sub_resource_idx)))
+        return E_INVALIDARG;
+
+    return wined3d_volume_unmap(volume_from_resource(sub_resource));
+}
+
+static const struct wined3d_resource_ops texture3d_resource_ops =
+{
+    texture_resource_incref,
+    texture_resource_decref,
+    wined3d_texture_unload,
+    texture3d_resource_sub_resource_map,
+    texture3d_resource_sub_resource_unmap,
+};
+
 static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
         UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
@@ -1560,7 +1607,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
     }
 
     if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels, desc,
-            0, device, parent, parent_ops, &texture_resource_ops)))
+            0, device, parent, parent_ops, &texture3d_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
 #if defined(STAGING_CSMT)
@@ -1600,6 +1647,30 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
     return WINED3D_OK;
 }
 
+HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const RECT *dst_rect_in,
+        struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const RECT *src_rect_in, DWORD flags,
+        const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_resource *dst_resource, *src_resource = NULL;
+
+    TRACE("dst_texture %p, dst_sub_resource_idx %u, src_texture %p, src_sub_resource_idx %u.\n",
+            dst_texture, dst_sub_resource_idx, src_texture, src_sub_resource_idx);
+
+    if (!(dst_resource = wined3d_texture_get_sub_resource(dst_texture, dst_sub_resource_idx))
+            || dst_resource->type != WINED3D_RTYPE_SURFACE)
+        return WINED3DERR_INVALIDCALL;
+
+    if (src_texture)
+    {
+        if (!(src_resource = wined3d_texture_get_sub_resource(src_texture, src_sub_resource_idx))
+                || src_resource->type != WINED3D_RTYPE_SURFACE)
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    return wined3d_surface_blt(surface_from_resource(dst_resource), dst_rect_in,
+        src_resource ? surface_from_resource(src_resource) : NULL, src_rect_in, flags, fx, filter);
+}
+
 HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
         UINT level_count, DWORD surface_flags, const struct wined3d_sub_resource_data *data, void *parent,
         const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
@@ -1650,11 +1721,51 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
 
     /* FIXME: We'd like to avoid ever allocating system memory for the texture
      * in this case. */
-    if (data)
-        wined3d_texture_upload_data(object, data);
+    if (data && FAILED(hr = wined3d_texture_upload_data(object, data)))
+    {
+        wined3d_texture_cleanup(object);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
 
     TRACE("Created texture %p.\n", object);
     *texture = object;
 
     return WINED3D_OK;
 }
+
+HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc)
+{
+    struct wined3d_resource *sub_resource;
+
+    TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    if (sub_resource->type != WINED3D_RTYPE_SURFACE)
+    {
+        WARN("Not supported on %s resources.\n", debug_d3dresourcetype(texture->resource.type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return wined3d_surface_getdc(surface_from_resource(sub_resource), dc);
+}
+
+HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc)
+{
+    struct wined3d_resource *sub_resource;
+
+    TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    if (sub_resource->type != WINED3D_RTYPE_SURFACE)
+    {
+        WARN("Not supported on %s resources.\n", debug_d3dresourcetype(texture->resource.type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return wined3d_surface_releasedc(surface_from_resource(sub_resource), dc);
+}
index 446edc6..8744c6b 100644 (file)
@@ -88,6 +88,7 @@ static const struct wined3d_format_channels formats[] =
     {WINED3DFMT_R10G10B10A2_UINT,          10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
     {WINED3DFMT_R10G10B10A2_SNORM,         10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
     {WINED3DFMT_R8G8B8A8_UNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R8G8B8A8_UNORM_SRGB,        8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
     {WINED3DFMT_R8G8B8A8_UINT,              8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
     {WINED3DFMT_R8G8B8X8_UNORM,             8,  8,  8,  0,   0,  8, 16,  0,    4,   0,     0},
     {WINED3DFMT_R16G16_UNORM,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
@@ -277,8 +278,8 @@ static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, U
             for (x = 0; x < width; x++ )
             {
                 unsigned char color = (*Source++);
-                /* A */ Dest[1] = (color & 0xf0) << 0;
-                /* L */ Dest[0] = (color & 0x0f) << 4;
+                /* A */ Dest[1] = (color & 0xf0u) << 0;
+                /* L */ Dest[0] = (color & 0x0fu) << 4;
                 Dest += 2;
             }
         }
@@ -305,9 +306,9 @@ static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT src_row
             texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
             for (x = 0; x < width; x++ )
             {
-                l_in = (*texel_in & 0xfc00) >> 10;
-                g_in = (*texel_in & 0x03e0) >> 5;
-                r_in = *texel_in & 0x001f;
+                l_in = (*texel_in & 0xfc00u) >> 10;
+                g_in = (*texel_in & 0x03e0u) >> 5;
+                r_in = *texel_in & 0x001fu;
 
                 *texel_out = ((r_in + 16) << 11) | (l_in << 5) | (g_in + 16);
                 texel_out++;
@@ -332,9 +333,9 @@ static void convert_r5g5_snorm_l6_unorm_ext(const BYTE *src, BYTE *dst, UINT src
             texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
             for (x = 0; x < width; x++ )
             {
-                l_in = (*texel_in & 0xfc00) >> 10;
-                g_in = (*texel_in & 0x03e0) >> 5;
-                r_in = *texel_in & 0x001f;
+                l_in = (*texel_in & 0xfc00u) >> 10;
+                g_in = (*texel_in & 0x03e0u) >> 5;
+                r_in = *texel_in & 0x001fu;
 
                 r_out = r_in << 3;
                 if (!(r_in & 0x10)) /* r > 0 */
@@ -379,9 +380,9 @@ static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT src_
             texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
             for (x = 0; x < width; x++ )
             {
-                l_in = (*texel_in & 0xfc00) >> 10;
-                g_in = (*texel_in & 0x03e0) >> 5;
-                r_in = *texel_in & 0x001f;
+                l_in = (*texel_in & 0xfc00u) >> 10;
+                g_in = (*texel_in & 0x03e0u) >> 5;
+                r_in = *texel_in & 0x001fu;
 
                 ds_out = r_in << 3;
                 if (!(r_in & 0x10)) /* r > 0 */
@@ -651,7 +652,7 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p
 
             for (x = 0; x < width; ++x)
             {
-                dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8);
+                dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00u) >> 8);
                 dest_s[x * 2 + 1] = source[x] & 0xff;
             }
         }
@@ -718,9 +719,9 @@ static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsig
         {
             WORD src_color = src_row[x];
             if (!color_in_range(color_key, src_color))
-                dst_row[x] = 0x8000 | ((src_color & 0xffc0) >> 1) | (src_color & 0x1f);
+                dst_row[x] = 0x8000u | ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
             else
-                dst_row[x] = ((src_color & 0xffc0) >> 1) | (src_color & 0x1f);
+                dst_row[x] = ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
         }
     }
 }
@@ -1013,7 +1014,12 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_RENDERTARGET,
             WINED3D_GL_EXT_NONE,        NULL},
-    {WINED3DFMT_B5G5R5X1_UNORM,         GL_RGB5,                          GL_RGB5_A1,                             0,
+    {WINED3DFMT_B5G6R5_UNORM,           GL_RGB565,                        GL_RGB565,                        GL_RGB8,
+            GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            ARB_ES2_COMPATIBILITY,      NULL},
+    {WINED3DFMT_B5G5R5X1_UNORM,         GL_RGB5,                          GL_RGB5,                                0,
             GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
             WINED3D_GL_EXT_NONE,        NULL},
@@ -1552,13 +1558,133 @@ static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info
     while (gl_info->gl_ops.gl.p_glGetError());
 }
 
+static void draw_test_quad(struct wined3d_caps_gl_ctx *ctx, const struct wined3d_vec3 *geometry,
+        const struct wined3d_color *color)
+{
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    static const struct wined3d_vec3 default_geometry[] =
+    {
+        {-1.0f, -1.0f, 0.0f},
+        { 1.0f, -1.0f, 0.0f},
+        {-1.0f,  1.0f, 0.0f},
+        { 1.0f,  1.0f, 0.0f},
+    };
+    static const char vs_core_header[] =
+        "#version 150\n"
+        "in vec4 pos;\n"
+        "in vec4 color;\n"
+        "out vec4 out_color;\n"
+        "\n";
+    static const char vs_legacy_header[] =
+        "#version 120\n"
+        "attribute vec4 pos;\n"
+        "attribute vec4 color;\n"
+        "varying vec4 out_color;\n"
+        "\n";
+    static const char vs_body[] =
+        "void main()\n"
+        "{\n"
+        "    gl_Position = pos;\n"
+        "    out_color = color;\n"
+        "}\n";
+    static const char fs_core[] =
+        "#version 150\n"
+        "in vec4 out_color;\n"
+        "out vec4 fragment_color;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    fragment_color = out_color;\n"
+        "}\n";
+    static const char fs_legacy[] =
+        "#version 120\n"
+        "varying vec4 out_color;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragData[0] = out_color;\n"
+        "}\n";
+    const char *source[2];
+    GLuint vs_id, fs_id;
+    unsigned int i;
+
+    if (!geometry)
+        geometry = default_geometry;
+
+    if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] || !gl_info->supported[ARB_VERTEX_SHADER]
+            || !gl_info->supported[ARB_FRAGMENT_SHADER])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+
+        gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+        gl_info->gl_ops.gl.p_glColor4f(color->r, color->g, color->b, color->a);
+        for (i = 0; i < 4; ++i)
+            gl_info->gl_ops.gl.p_glVertex3fv(&geometry[i].x);
+        gl_info->gl_ops.gl.p_glEnd();
+        checkGLcall("Drawing a quad");
+        return;
+    }
+
+    if (!ctx->test_vbo)
+        GL_EXTCALL(glGenBuffers(1, &ctx->test_vbo));
+    GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, ctx->test_vbo));
+    GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(struct wined3d_vec3) * 4, geometry, GL_STREAM_DRAW));
+    GL_EXTCALL(glVertexAttribPointer(0, 3, GL_FLOAT, FALSE, 0, NULL));
+    GL_EXTCALL(glVertexAttrib4f(1, color->r, color->g, color->b, color->a));
+    GL_EXTCALL(glEnableVertexAttribArray(0));
+    GL_EXTCALL(glDisableVertexAttribArray(1));
+
+    if (!ctx->test_program_id)
+    {
+        ctx->test_program_id = GL_EXTCALL(glCreateProgram());
+
+        vs_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
+        source[0] = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? vs_legacy_header : vs_core_header;
+        source[1] = vs_body;
+        GL_EXTCALL(glShaderSource(vs_id, 2, source, NULL));
+        GL_EXTCALL(glAttachShader(ctx->test_program_id, vs_id));
+        GL_EXTCALL(glDeleteShader(vs_id));
+
+        fs_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
+        source[0] = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? fs_legacy : fs_core;
+        GL_EXTCALL(glShaderSource(fs_id, 1, source, NULL));
+        GL_EXTCALL(glAttachShader(ctx->test_program_id, fs_id));
+        GL_EXTCALL(glDeleteShader(fs_id));
+
+        GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 0, "pos"));
+        GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 1, "color"));
+
+        GL_EXTCALL(glCompileShader(vs_id));
+        print_glsl_info_log(gl_info, vs_id, FALSE);
+        GL_EXTCALL(glCompileShader(fs_id));
+        print_glsl_info_log(gl_info, fs_id, FALSE);
+        GL_EXTCALL(glLinkProgram(ctx->test_program_id));
+        shader_glsl_validate_link(gl_info, ctx->test_program_id);
+    }
+    GL_EXTCALL(glUseProgram(ctx->test_program_id));
+
+    gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+    GL_EXTCALL(glUseProgram(0));
+    GL_EXTCALL(glDisableVertexAttribArray(0));
+    GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
+    checkGLcall("Drawing a quad");
+}
+
 /* Context activation is done by the caller. */
-static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
+static void check_fbo_compat(struct wined3d_caps_gl_ctx *ctx, struct wined3d_format *format)
 {
     /* Check if the default internal format is supported as a frame buffer
      * target, otherwise fall back to the render target internal.
      *
      * Try to stick to the standard format if possible, this limits precision differences. */
+    static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 1.0f};
+    static const struct wined3d_color half_transparent_red = {1.0f, 0.0f, 0.0f, 0.5f};
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
     GLenum status, rt_internal = format->rtInternal;
     GLuint object, color_rb;
     enum wined3d_gl_resource_type type;
@@ -1692,32 +1818,13 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
                     gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
                 else
                     gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
-                gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
-                gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
-                gl_info->gl_ops.gl.p_glLoadIdentity();
-                gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
-                gl_info->gl_ops.gl.p_glLoadIdentity();
-
                 gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-                /* Draw a full-black quad */
-                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-                gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glEnd();
+                draw_test_quad(ctx, NULL, &black);
 
                 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
-                /* Draw a half-transparent red quad */
-                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-                gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glEnd();
+
+                draw_test_quad(ctx, NULL, &half_transparent_red);
 
                 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
 
@@ -1763,10 +1870,10 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
                 checkGLcall("Post-pixelshader blending check");
 
                 a = color >> 24;
-                r = (color & 0x00ff0000) >> 16;
+                r = (color & 0x00ff0000u) >> 16;
 
-                r_range = format->red_size < 8 ? 1 << (8 - format->red_size) : 1;
-                a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size) : 1;
+                r_range = format->red_size < 8 ? 1u << (8 - format->red_size) : 1;
+                a_range = format->alpha_size < 8 ? 1u << (8 - format->alpha_size) : 1;
                 if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
                     match = FALSE;
                 else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
@@ -1863,8 +1970,9 @@ static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_fo
 }
 
 /* Context activation is done by the caller. */
-static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
+static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx)
 {
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
     unsigned int i, type;
     GLuint fbo;
 
@@ -1997,7 +2105,7 @@ static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
         {
             TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
-            check_fbo_compat(gl_info, format);
+            check_fbo_compat(ctx, format);
         }
         else
         {
@@ -2268,7 +2376,8 @@ static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3
         /* This was already handled by init_format_texture_info(). */
         return;
 
-    if(wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
     {
         WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
         if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
@@ -2419,6 +2528,13 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
     gl_info->formats[idx].height_scale.denominator = 2;
     gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_NV12);
 
+    if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    {
+        idx = getFmtIdx(WINED3DFMT_INTZ);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X);
+    }
+
     if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
     {
         idx = getFmtIdx(WINED3DFMT_P8_UINT);
@@ -2577,7 +2693,7 @@ BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info)
 }
 
 /* Context activation is done by the caller. */
-BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter)
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx)
 {
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
 
@@ -2588,7 +2704,7 @@ BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter)
     if (!init_format_vertex_info(gl_info)) goto fail;
 
     apply_format_fixups(adapter, gl_info);
-    init_format_fbo_compat_info(gl_info);
+    init_format_fbo_compat_info(ctx);
     init_format_filter_info(gl_info, adapter->driver_info.vendor);
 
     return TRUE;
@@ -2599,6 +2715,100 @@ fail:
     return FALSE;
 }
 
+float wined3d_adapter_find_polyoffset_scale(struct wined3d_caps_gl_ctx *ctx, GLenum format)
+{
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    static const struct wined3d_color blue = {0.0f, 0.0f, 1.0f, 1.0f};
+    GLuint fbo, color, depth;
+    unsigned int low = 0, high = 32, cur;
+    DWORD readback[256];
+    static const struct wined3d_vec3 geometry[] =
+    {
+        {-1.0f, -1.0f, -1.0f},
+        { 1.0f, -1.0f,  0.0f},
+        {-1.0f,  1.0f, -1.0f},
+        { 1.0f,  1.0f,  0.0f},
+    };
+
+    /* Most drivers want 2^23 for fixed point depth buffers, including r300g, r600g,
+     * Nvidia. Use this as a fallback if the detection fails. */
+    unsigned int fallback = 23;
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+    {
+        FIXME("No FBOs, assuming polyoffset scale of 2^%u.\n", fallback);
+        return (float)(1u << fallback);
+    }
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &color);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, color);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+
+    gl_info->fbo_ops.glGenRenderbuffers(1, &depth);
+    gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, depth);
+    gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, format, 256, 1);
+
+    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
+    gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
+    checkGLcall("Setup framebuffer");
+
+    gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
+    gl_info->gl_ops.gl.p_glClearDepth(0.5f);
+    gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
+    gl_info->gl_ops.gl.p_glEnable(GL_POLYGON_OFFSET_FILL);
+    gl_info->gl_ops.gl.p_glViewport(0, 0, 256, 1);
+    checkGLcall("Misc parameters");
+
+    for (;;)
+    {
+        if (high - low <= 1)
+        {
+            ERR("PolygonOffset scale factor detection failed, using fallback value 2^%u.\n", fallback);
+            cur = fallback;
+            break;
+        }
+        cur = (low + high) / 2;
+
+        gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        /* The post viewport transform Z of the geometry runs from 0.0 to 0.5. We want to push it another
+         * 0.25 so that the Z buffer content (0.5) cuts the quad off at half the screen. */
+        gl_info->gl_ops.gl.p_glPolygonOffset(0.0f, (float)(1u << cur) * 0.25f);
+        draw_test_quad(ctx, geometry, &blue);
+        checkGLcall("Test draw");
+
+        /* Rebinding texture to workaround a fglrx bug. */
+        gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, color);
+        gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+        checkGLcall("readback");
+
+        TRACE("low %02u, high %02u, cur %2u, 0=0x%08x, 125=0x%08x, 131=0x%08x, 255=0x%08x\n",
+                low, high, cur, readback[0], readback[125], readback[131], readback[255]);
+
+        if ((readback[125] & 0xff) < 0xa0)
+            high = cur;
+        else if ((readback[131] & 0xff) > 0xa0)
+            low = cur;
+        else
+        {
+            TRACE("Found scale factor 2^%u for format %x\n", cur, format);
+            break;
+        }
+    }
+
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &color);
+    gl_info->fbo_ops.glDeleteRenderbuffers(1, &depth);
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    checkGLcall("Delete framebuffer");
+
+    gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
+    gl_info->gl_ops.gl.p_glDisable(GL_POLYGON_OFFSET_FILL);
+    return (float)(1u << cur);
+}
+
 const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
         enum wined3d_format_id format_id)
 {
@@ -3694,12 +3904,12 @@ void get_texture_matrix(const struct wined3d_context *context, const struct wine
     compute_texture_matrix(gl_info, &state->transforms[WINED3D_TS_TEXTURE0 + tex],
             state->texture_states[tex][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS],
             generated, context->last_was_rhw,
-            context->stream_info.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))
+            context->stream_info.use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))
             ? context->stream_info.elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->id
             : WINED3DFMT_UNKNOWN,
             device->shader_backend->shader_has_ffp_proj_control(device->shader_priv), mat);
 
-    if ((context->lastWasPow2Texture & (1 << tex)) && state->textures[tex])
+    if ((context->lastWasPow2Texture & (1u << tex)) && state->textures[tex])
     {
         if (generated)
             FIXME("Non-power-of-two texture being used with generated texture coords.\n");
@@ -3820,77 +4030,6 @@ unsigned int count_bits(unsigned int mask)
     return count;
 }
 
-/* Helper function for retrieving color info for ChoosePixelFormat and wglChoosePixelFormatARB.
- * The later function requires individual color components. */
-BOOL getColorBits(const struct wined3d_format *format,
-        BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize)
-{
-    TRACE("format %s.\n", debug_d3dformat(format->id));
-
-    switch (format->id)
-    {
-        case WINED3DFMT_B10G10R10A2_UNORM:
-        case WINED3DFMT_R10G10B10A2_UNORM:
-        case WINED3DFMT_B8G8R8X8_UNORM:
-        case WINED3DFMT_B8G8R8_UNORM:
-        case WINED3DFMT_B8G8R8A8_UNORM:
-        case WINED3DFMT_R8G8B8A8_UNORM:
-        case WINED3DFMT_B5G5R5X1_UNORM:
-        case WINED3DFMT_B5G5R5A1_UNORM:
-        case WINED3DFMT_B5G6R5_UNORM:
-        case WINED3DFMT_B4G4R4X4_UNORM:
-        case WINED3DFMT_B4G4R4A4_UNORM:
-        case WINED3DFMT_B2G3R3_UNORM:
-        case WINED3DFMT_P8_UINT_A8_UNORM:
-        case WINED3DFMT_P8_UINT:
-            break;
-        default:
-            FIXME("Unsupported format %s.\n", debug_d3dformat(format->id));
-            return FALSE;
-    }
-
-    *redSize = format->red_size;
-    *greenSize = format->green_size;
-    *blueSize = format->blue_size;
-    *alphaSize = format->alpha_size;
-    *totalSize = *redSize + *greenSize + *blueSize + *alphaSize;
-
-    TRACE("Returning red: %d, green: %d, blue: %d, alpha: %d, total: %d for format %s.\n",
-            *redSize, *greenSize, *blueSize, *alphaSize, *totalSize, debug_d3dformat(format->id));
-    return TRUE;
-}
-
-/* Helper function for retrieving depth/stencil info for ChoosePixelFormat and wglChoosePixelFormatARB */
-BOOL getDepthStencilBits(const struct wined3d_format *format, BYTE *depthSize, BYTE *stencilSize)
-{
-    TRACE("format %s.\n", debug_d3dformat(format->id));
-
-    switch (format->id)
-    {
-        case WINED3DFMT_D16_LOCKABLE:
-        case WINED3DFMT_D16_UNORM:
-        case WINED3DFMT_S1_UINT_D15_UNORM:
-        case WINED3DFMT_X8D24_UNORM:
-        case WINED3DFMT_S4X4_UINT_D24_UNORM:
-        case WINED3DFMT_D24_UNORM_S8_UINT:
-        case WINED3DFMT_S8_UINT_D24_FLOAT:
-        case WINED3DFMT_D32_UNORM:
-        case WINED3DFMT_D32_FLOAT:
-        case WINED3DFMT_INTZ:
-            break;
-        default:
-            FIXME("Unsupported depth/stencil format %s.\n", debug_d3dformat(format->id));
-            return FALSE;
-    }
-
-    *depthSize = format->depth_size;
-    *stencilSize = format->stencil_size;
-
-    TRACE("Returning depthSize: %d and stencilSize: %d for format %s.\n",
-            *depthSize, *stencilSize, debug_d3dformat(format->id));
-    return TRUE;
-}
-
 /* Note: It's the caller's responsibility to ensure values can be expressed
  * in the requested format. UNORM formats for example can only express values
  * in the range 0.0f -> 1.0f. */
@@ -3956,7 +4095,7 @@ DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface, c
 
 static float color_to_float(DWORD color, DWORD size, DWORD offset)
 {
-    DWORD mask = (1 << size) - 1;
+    DWORD mask = (1u << size) - 1;
 
     if (!size)
         return 1.0f;
@@ -4018,6 +4157,72 @@ BOOL wined3d_format_convert_color_to_float(const struct wined3d_format *format,
     }
 }
 
+void wined3d_format_get_float_color_key(const struct wined3d_format *format,
+        const struct wined3d_color_key *key, struct wined3d_color *float_colors)
+{
+    struct wined3d_color slop;
+
+    switch (format->id)
+    {
+        case WINED3DFMT_B8G8R8_UNORM:
+        case WINED3DFMT_B8G8R8A8_UNORM:
+        case WINED3DFMT_B8G8R8X8_UNORM:
+        case WINED3DFMT_B5G6R5_UNORM:
+        case WINED3DFMT_B5G5R5X1_UNORM:
+        case WINED3DFMT_B5G5R5A1_UNORM:
+        case WINED3DFMT_B4G4R4A4_UNORM:
+        case WINED3DFMT_B2G3R3_UNORM:
+        case WINED3DFMT_R8_UNORM:
+        case WINED3DFMT_A8_UNORM:
+        case WINED3DFMT_B2G3R3A8_UNORM:
+        case WINED3DFMT_B4G4R4X4_UNORM:
+        case WINED3DFMT_R10G10B10A2_UNORM:
+        case WINED3DFMT_R10G10B10A2_SNORM:
+        case WINED3DFMT_R8G8B8A8_UNORM:
+        case WINED3DFMT_R8G8B8X8_UNORM:
+        case WINED3DFMT_R16G16_UNORM:
+        case WINED3DFMT_B10G10R10A2_UNORM:
+            slop.r = 0.5f / ((1 << format->red_size) - 1);
+            slop.g = 0.5f / ((1 << format->green_size) - 1);
+            slop.b = 0.5f / ((1 << format->blue_size) - 1);
+            slop.a = 0.5f / ((1 << format->alpha_size) - 1);
+
+            float_colors[0].r = color_to_float(key->color_space_low_value, format->red_size, format->red_offset)
+                    - slop.r;
+            float_colors[0].g = color_to_float(key->color_space_low_value, format->green_size, format->green_offset)
+                    - slop.g;
+            float_colors[0].b = color_to_float(key->color_space_low_value, format->blue_size, format->blue_offset)
+                    - slop.b;
+            float_colors[0].a = color_to_float(key->color_space_low_value, format->alpha_size, format->alpha_offset)
+                    - slop.a;
+
+            float_colors[1].r = color_to_float(key->color_space_high_value, format->red_size, format->red_offset)
+                    + slop.r;
+            float_colors[1].g = color_to_float(key->color_space_high_value, format->green_size, format->green_offset)
+                    + slop.g;
+            float_colors[1].b = color_to_float(key->color_space_high_value, format->blue_size, format->blue_offset)
+                    + slop.b;
+            float_colors[1].a = color_to_float(key->color_space_high_value, format->alpha_size, format->alpha_offset)
+                    + slop.a;
+            break;
+
+        case WINED3DFMT_P8_UINT:
+            float_colors[0].r = 0.0f;
+            float_colors[0].g = 0.0f;
+            float_colors[0].b = 0.0f;
+            float_colors[0].a = (key->color_space_low_value - 0.5f) / 255.0f;
+
+            float_colors[1].r = 0.0f;
+            float_colors[1].g = 0.0f;
+            float_colors[1].b = 0.0f;
+            float_colors[1].a = (key->color_space_high_value + 0.5f) / 255.0f;
+            break;
+
+        default:
+            ERR("Unhandled color key to float conversion for format %s.\n", debug_d3dformat(format->id));
+    }
+}
+
 /* DirectDraw stuff */
 enum wined3d_format_id pixelformat_for_depth(DWORD depth)
 {
@@ -4088,6 +4293,13 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
     return size;
 }
 
+unsigned int wined3d_max_compat_varyings(const struct wined3d_gl_info *gl_info)
+{
+    /* On core profile we have to also count diffuse and specular colors and the
+     * fog coordinate. */
+    return gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? MAX_TEXTURES * 4 : (MAX_TEXTURES + 2) * 4 + 1;
+}
+
 void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
         struct ffp_frag_settings *settings, BOOL ignore_textype)
 {
@@ -4371,6 +4583,48 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
         settings->color_key_enabled = 1;
     else
         settings->color_key_enabled = 0;
+
+    /* texcoords_initialized is set to meaningful values only when GL doesn't
+     * support enough varyings to always pass around all the possible texture
+     * coordinates.
+     * This is used to avoid reading a varying not written by the vertex shader.
+     * Reading uninitialized varyings on core profile contexts results in an
+     * error while with builtin varyings on legacy contexts you get undefined
+     * behavior. */
+    if (d3d_info->limits.varying_count
+            && d3d_info->limits.varying_count < wined3d_max_compat_varyings(gl_info))
+    {
+        settings->texcoords_initialized = 0;
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            if (use_vs(state))
+            {
+                if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.output_registers & (1u << i))
+                    settings->texcoords_initialized |= 1u << i;
+            }
+            else
+            {
+                const struct wined3d_stream_info *si = &context->stream_info;
+                unsigned int coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+                if ((state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                        & WINED3D_FFP_TCI_MASK
+                        || (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))))
+                    settings->texcoords_initialized |= 1u << i;
+            }
+        }
+    }
+    else
+    {
+        settings->texcoords_initialized = (1u << MAX_TEXTURES) - 1;
+    }
+
+    settings->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
+            && state->gl_primitive_type == GL_POINTS;
+
+    if (d3d_info->emulated_flatshading)
+        settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
+    else
+        settings->flatshading = FALSE;
 }
 
 const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
@@ -4530,9 +4784,12 @@ const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
     ffp_frag_program_key_compare,
 };
 
-void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
-        struct wined3d_ffp_vs_settings *settings)
+void wined3d_ffp_get_vs_settings(const struct wined3d_context *context,
+        const struct wined3d_state *state, struct wined3d_ffp_vs_settings *settings)
 {
+    const struct wined3d_stream_info *si = &context->stream_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     unsigned int coord_idx, i;
 
     if (si->position_transformed)
@@ -4541,7 +4798,7 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
 
         settings->transformed = 1;
         settings->point_size = state->gl_primitive_type == GL_POINTS;
-        settings->per_vertex_point_size = !!(si->use_map & 1 << WINED3D_FFP_PSIZE);
+        settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE);
         if (!state->render_states[WINED3D_RS_FOGENABLE])
             settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
         else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
@@ -4552,10 +4809,18 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
         for (i = 0; i < MAX_TEXTURES; ++i)
         {
             coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
-            if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
-                settings->texcoords |= 1 << i;
+            if (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+                settings->texcoords |= 1u << i;
             settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
         }
+        if (d3d_info->limits.varying_count >= wined3d_max_compat_varyings(gl_info))
+            settings->texcoords = (1u << MAX_TEXTURES) - 1;
+
+        if (d3d_info->emulated_flatshading)
+            settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
+        else
+            settings->flatshading = FALSE;
+
         return;
     }
 
@@ -4575,14 +4840,14 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
     settings->transformed = 0;
     settings->clipping = state->render_states[WINED3D_RS_CLIPPING]
             && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
-    settings->normal = !!(si->use_map & (1 << WINED3D_FFP_NORMAL));
+    settings->normal = !!(si->use_map & (1u << WINED3D_FFP_NORMAL));
     settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS];
     settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING];
     settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
     settings->point_size = state->gl_primitive_type == GL_POINTS;
-    settings->per_vertex_point_size = !!(si->use_map & 1 << WINED3D_FFP_PSIZE);
+    settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE);
 
-    if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1 << WINED3D_FFP_DIFFUSE)))
+    if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1u << WINED3D_FFP_DIFFUSE)))
     {
         settings->diffuse_source = state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE];
         settings->emissive_source = state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE];
@@ -4601,10 +4866,12 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
     for (i = 0; i < MAX_TEXTURES; ++i)
     {
         coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
-        if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
-            settings->texcoords |= 1 << i;
+        if (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+            settings->texcoords |= 1u << i;
         settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
     }
+    if (d3d_info->limits.varying_count >= wined3d_max_compat_varyings(gl_info))
+        settings->texcoords = (1u << MAX_TEXTURES) - 1;
 
     settings->light_type = 0;
     for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
@@ -4634,6 +4901,11 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
     else
         settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
 
+    if (d3d_info->emulated_flatshading)
+        settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
+    else
+        settings->flatshading = FALSE;
+
     settings->padding = 0;
 }
 
index b2f69e9..3d669a1 100644 (file)
@@ -145,8 +145,8 @@ HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_rendertarget
 {
     struct wined3d_rendertarget_view *object;
 
-    TRACE("desc %p, resource %p, parent %p, view %p.\n",
-            desc, resource, parent, view);
+    TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
+            desc, resource, parent, parent_ops, view);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
@@ -164,7 +164,7 @@ HRESULT CDECL wined3d_rendertarget_view_create_from_surface(struct wined3d_surfa
 {
     struct wined3d_rendertarget_view_desc desc;
 
-    TRACE("surface %p, view %p.\n", surface, view);
+    TRACE("surface %p, parent %p, parent_ops %p, view %p.\n", surface, parent, parent_ops, view);
 
     desc.format_id = surface->resource.format->id;
     desc.u.texture.level_idx = surface->texture_level;
@@ -174,6 +174,28 @@ HRESULT CDECL wined3d_rendertarget_view_create_from_surface(struct wined3d_surfa
     return wined3d_rendertarget_view_create(&desc, &surface->container->resource, parent, parent_ops, view);
 }
 
+HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_rendertarget_view **view)
+{
+    struct wined3d_resource *sub_resource;
+
+    TRACE("texture %p, sub_resource_idx %u, parent %p, parent_ops %p, view %p.\n",
+            texture, sub_resource_idx, parent, parent_ops, view);
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    if (sub_resource->type != WINED3D_RTYPE_SURFACE)
+    {
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(texture->resource.type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return wined3d_rendertarget_view_create_from_surface(surface_from_resource(sub_resource),
+            parent, parent_ops, view);
+}
+
 ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
 {
     ULONG refcount = InterlockedIncrement(&view->refcount);
@@ -213,7 +235,7 @@ HRESULT CDECL wined3d_shader_resource_view_create(struct wined3d_resource *resou
 {
     struct wined3d_shader_resource_view *object;
 
-    TRACE("parent %p, parent_ops %p, view %p.\n", parent, parent_ops, view);
+    TRACE("resource %p, parent %p, parent_ops %p, view %p.\n", resource, parent, parent_ops, view);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
index 013884b..d7da5a8 100644 (file)
@@ -38,6 +38,32 @@ BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
     return TRUE;
 }
 
+#if !defined(STAGING_CSMT)
+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch)
+{
+    const struct wined3d_format *format = volume->resource.format;
+
+    if (volume->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+    {
+        /* Since compressed formats are block based, pitch means the amount of
+         * bytes to the next row of block rather than the next row of pixels. */
+        UINT row_block_count = (volume->resource.width + format->block_width - 1) / format->block_width;
+        UINT slice_block_count = (volume->resource.height + format->block_height - 1) / format->block_height;
+        *row_pitch = row_block_count * format->block_byte_count;
+        *slice_pitch = *row_pitch * slice_block_count;
+    }
+    else
+    {
+        unsigned char alignment = volume->resource.device->surface_alignment;
+        *row_pitch = format->byte_count * volume->resource.width;  /* Bytes / row */
+        *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1);
+        *slice_pitch = *row_pitch * volume->resource.height;
+    }
+
+    TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch);
+}
+
+#endif /* STAGING_CSMT */
 /* This call just uploads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
@@ -69,7 +95,11 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
         dst_row_pitch = width * format->conv_byte_count;
         dst_slice_pitch = dst_row_pitch * height;
 
+#if defined(STAGING_CSMT)
         wined3d_resource_get_pitch(&volume->resource, &src_row_pitch, &src_slice_pitch);
+#else  /* STAGING_CSMT */
+        wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch);
+#endif /* STAGING_CSMT */
 
         converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth);
         format->convert(data->addr, converted_mem, src_row_pitch, src_slice_pitch,
@@ -558,46 +588,6 @@ static void volume_unload(struct wined3d_resource *resource)
     resource_unload(resource);
 }
 
-ULONG CDECL wined3d_volume_incref(struct wined3d_volume *volume)
-{
-    TRACE("Forwarding to container %p.\n", volume->container);
-
-    return wined3d_texture_incref(volume->container);
-}
-
-#if defined(STAGING_CSMT)
-void wined3d_volume_cleanup_cs(struct wined3d_volume *volume)
-{
-    HeapFree(GetProcessHeap(), 0, volume);
-}
-
-#endif /* STAGING_CSMT */
-ULONG CDECL wined3d_volume_decref(struct wined3d_volume *volume)
-{
-    TRACE("Forwarding to container %p.\n", volume->container);
-
-    return wined3d_texture_decref(volume->container);
-}
-
-void * CDECL wined3d_volume_get_parent(const struct wined3d_volume *volume)
-{
-    TRACE("volume %p.\n", volume);
-
-    return volume->resource.parent;
-}
-
-void CDECL wined3d_volume_preload(struct wined3d_volume *volume)
-{
-    FIXME("volume %p stub!\n", volume);
-}
-
-struct wined3d_resource * CDECL wined3d_volume_get_resource(struct wined3d_volume *volume)
-{
-    TRACE("volume %p.\n", volume);
-
-    return &volume->resource;
-}
-
 #if !defined(STAGING_CSMT)
 static BOOL volume_check_block_align(const struct wined3d_volume *volume,
         const struct wined3d_box *box)
@@ -650,7 +640,7 @@ static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *vol
     return TRUE;
 }
 
-HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
+HRESULT wined3d_volume_map(struct wined3d_volume *volume,
         struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
 {
 #if defined(STAGING_CSMT)
@@ -669,8 +659,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
         WARN("Map box is invalid.\n");
         return WINED3DERR_INVALIDCALL;
     }
-    if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) &&
-            !wined3d_resource_check_block_align(&volume->resource, box))
+    if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !wined3d_resource_check_block_align(&volume->resource, box))
     {
         WARN("Map box is misaligned for %ux%u blocks.\n",
                 format->block_width, format->block_height);
@@ -682,6 +671,19 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
         return hr;
 
     return hr;
+}
+
+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume)
+{
+    HRESULT hr;
+
+    if (volume->resource.unmap_dirtify)
+        wined3d_texture_set_dirty(volume->container);
+
+    hr = wined3d_resource_unmap(&volume->resource);
+    if (hr == WINEDDERR_NOTLOCKED)
+        return WINED3DERR_INVALIDCALL;
+    return hr;
 #else  /* STAGING_CSMT */
     struct wined3d_device *device = volume->resource.device;
     struct wined3d_context *context;
@@ -780,7 +782,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
     }
     else
     {
-        wined3d_resource_get_pitch(&volume->resource, &map_desc->row_pitch, &map_desc->slice_pitch);
+        wined3d_volume_get_pitch(volume, &map_desc->row_pitch, &map_desc->slice_pitch);
     }
 
     if (!box)
@@ -823,27 +825,10 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
             map_desc->data, map_desc->row_pitch, map_desc->slice_pitch);
 
     return WINED3D_OK;
-#endif /* STAGING_CSMT */
-}
-
-struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resource *resource)
-{
-    return volume_from_resource(resource);
 }
 
-HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume)
+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume)
 {
-#if defined(STAGING_CSMT)
-    HRESULT hr;
-
-    if (volume->resource.unmap_dirtify)
-        wined3d_texture_set_dirty(volume->container);
-
-    hr = wined3d_resource_unmap(&volume->resource);
-    if (hr == WINEDDERR_NOTLOCKED)
-        return WINED3DERR_INVALIDCALL;
-    return hr;
-#else  /* STAGING_CSMT */
     TRACE("volume %p.\n", volume);
 
     if (!volume->resource.map_count)
@@ -874,12 +859,38 @@ HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume)
 
 static ULONG volume_resource_incref(struct wined3d_resource *resource)
 {
-    return wined3d_volume_incref(volume_from_resource(resource));
+    struct wined3d_volume *volume = volume_from_resource(resource);
+    TRACE("Forwarding to container %p.\n", volume->container);
+
+    return wined3d_texture_incref(volume->container);
+}
+
+#if defined(STAGING_CSMT)
+void wined3d_volume_cleanup_cs(struct wined3d_volume *volume)
+{
+    HeapFree(GetProcessHeap(), 0, volume);
 }
 
+#endif /* STAGING_CSMT */
 static ULONG volume_resource_decref(struct wined3d_resource *resource)
 {
-    return wined3d_volume_decref(volume_from_resource(resource));
+    struct wined3d_volume *volume = volume_from_resource(resource);
+    TRACE("Forwarding to container %p.\n", volume->container);
+
+    return wined3d_texture_decref(volume->container);
+}
+
+static HRESULT volume_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)
+{
+    ERR("Not supported on sub-resources.\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+static HRESULT volume_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
+{
+    ERR("Not supported on sub-resources.\n");
+    return WINED3DERR_INVALIDCALL;
 }
 
 #if defined(STAGING_CSMT)
@@ -891,19 +902,17 @@ static void wined3d_volume_location_invalidated(struct wined3d_resource *resourc
         wined3d_texture_set_dirty(volume->container);
 }
 
+#endif /* STAGING_CSMT */
 static const struct wined3d_resource_ops volume_resource_ops =
 {
     volume_resource_incref,
     volume_resource_decref,
     volume_unload,
+    volume_resource_sub_resource_map,
+    volume_resource_sub_resource_unmap,
+#if defined(STAGING_CSMT)
     wined3d_volume_location_invalidated,
     wined3d_volume_load_location,
-#else  /* STAGING_CSMT */
-static const struct wined3d_resource_ops volume_resource_ops =
-{
-    volume_resource_incref,
-    volume_resource_decref,
-    volume_unload,
 #endif /* STAGING_CSMT */
 };
 
@@ -983,7 +992,7 @@ HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wi
     }
 
     if (FAILED(hr = device_parent->ops->volume_created(device_parent,
-            wined3d_texture_get_parent(container), object, &parent, &parent_ops)))
+            container, level, &parent, &parent_ops)))
     {
         WARN("Failed to create volume parent, hr %#x.\n", hr);
         wined3d_volume_destroy(object);
index 9bf3194..91d9850 100644 (file)
@@ -38,6 +38,7 @@
 @ cdecl wined3d_device_clear(ptr long ptr long ptr float long)
 @ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr ptr)
 @ cdecl wined3d_device_copy_resource(ptr ptr ptr)
+@ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr)
 @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr)
 @ cdecl wined3d_device_decref(ptr)
 @ cdecl wined3d_device_draw_indexed_primitive(ptr long long)
@@ -48,7 +49,6 @@
 @ cdecl wined3d_device_end_stateblock(ptr ptr)
 @ cdecl wined3d_device_evict_managed_resources(ptr)
 @ cdecl wined3d_device_get_available_texture_mem(ptr)
-@ cdecl wined3d_device_get_back_buffer(ptr long long long ptr)
 @ cdecl wined3d_device_get_base_vertex_index(ptr)
 @ cdecl wined3d_device_get_clip_plane(ptr long ptr)
 @ cdecl wined3d_device_get_clip_status(ptr ptr)
@@ -56,7 +56,6 @@
 @ cdecl wined3d_device_get_depth_stencil_view(ptr)
 @ cdecl wined3d_device_get_device_caps(ptr ptr)
 @ cdecl wined3d_device_get_display_mode(ptr long ptr ptr)
-@ cdecl wined3d_device_get_front_buffer_data(ptr long ptr)
 @ cdecl wined3d_device_get_gamma_ramp(ptr long ptr)
 @ cdecl wined3d_device_get_geometry_shader(ptr)
 @ cdecl wined3d_device_get_gs_cb(ptr long)
 @ cdecl wined3d_device_init_3d(ptr ptr)
 @ cdecl wined3d_device_init_gdi(ptr ptr)
 @ cdecl wined3d_device_multiply_transform(ptr long ptr)
-@ cdecl wined3d_device_present(ptr ptr ptr ptr ptr long)
 @ cdecl wined3d_device_process_vertices(ptr long long long ptr ptr long long)
 @ cdecl wined3d_device_release_focus_window(ptr)
 @ cdecl wined3d_device_reset(ptr ptr ptr ptr long)
 @ cdecl wined3d_device_set_clip_plane(ptr long ptr)
 @ cdecl wined3d_device_set_clip_status(ptr ptr)
 @ cdecl wined3d_device_set_cursor_position(ptr long long long)
-@ cdecl wined3d_device_set_cursor_properties(ptr long long ptr)
+@ cdecl wined3d_device_set_cursor_properties(ptr long long ptr long)
 @ cdecl wined3d_device_set_depth_stencil_view(ptr ptr)
 @ cdecl wined3d_device_set_dialog_box_mode(ptr long)
 @ cdecl wined3d_device_set_gamma_ramp(ptr long long ptr)
 @ cdecl wined3d_device_show_cursor(ptr long)
 @ cdecl wined3d_device_uninit_3d(ptr)
 @ cdecl wined3d_device_uninit_gdi(ptr)
+@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long)
 @ cdecl wined3d_device_update_surface(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_device_update_texture(ptr ptr ptr)
 @ cdecl wined3d_device_validate_device(ptr ptr)
 
 @ cdecl wined3d_resource_get_desc(ptr ptr)
 @ cdecl wined3d_resource_get_parent(ptr)
-@ cdecl wined3d_resource_get_pitch(ptr ptr ptr)
 @ cdecl wined3d_resource_get_priority(ptr)
 @ cdecl wined3d_resource_set_parent(ptr ptr)
 @ cdecl wined3d_resource_set_priority(ptr long)
+@ cdecl wined3d_resource_sub_resource_map(ptr long ptr ptr long)
+@ cdecl wined3d_resource_sub_resource_unmap(ptr long)
 
 @ cdecl wined3d_rendertarget_view_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_rendertarget_view_create_from_surface(ptr ptr ptr ptr)
+@ cdecl wined3d_rendertarget_view_create_from_sub_resource(ptr long ptr ptr ptr)
 @ cdecl wined3d_rendertarget_view_decref(ptr)
 @ cdecl wined3d_rendertarget_view_get_parent(ptr)
 @ cdecl wined3d_rendertarget_view_get_resource(ptr)
 @ cdecl wined3d_surface_blt(ptr ptr ptr ptr long ptr long)
 @ cdecl wined3d_surface_decref(ptr)
 @ cdecl wined3d_surface_from_resource(ptr)
-@ cdecl wined3d_surface_get_blt_status(ptr long)
-@ cdecl wined3d_surface_get_flip_status(ptr long)
 @ cdecl wined3d_surface_get_overlay_position(ptr ptr ptr)
 @ cdecl wined3d_surface_get_parent(ptr)
-@ cdecl wined3d_surface_get_render_target_data(ptr ptr)
+@ cdecl wined3d_surface_get_pitch(ptr)
 @ cdecl wined3d_surface_get_resource(ptr)
 @ cdecl wined3d_surface_getdc(ptr ptr)
 @ cdecl wined3d_surface_incref(ptr)
 @ cdecl wined3d_swapchain_get_back_buffer(ptr long long)
 @ cdecl wined3d_swapchain_get_device(ptr)
 @ cdecl wined3d_swapchain_get_display_mode(ptr ptr ptr)
-@ cdecl wined3d_swapchain_get_front_buffer_data(ptr ptr)
+@ cdecl wined3d_swapchain_get_front_buffer_data(ptr ptr long)
 @ cdecl wined3d_swapchain_get_gamma_ramp(ptr ptr)
 @ cdecl wined3d_swapchain_get_parent(ptr)
 @ cdecl wined3d_swapchain_get_desc(ptr ptr)
 @ cdecl wined3d_swapchain_get_raster_status(ptr ptr)
 @ cdecl wined3d_swapchain_incref(ptr)
 @ cdecl wined3d_swapchain_present(ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long)
 @ cdecl wined3d_swapchain_set_gamma_ramp(ptr long ptr)
 @ cdecl wined3d_swapchain_set_palette(ptr ptr)
 @ cdecl wined3d_swapchain_set_window(ptr ptr)
 
 @ cdecl wined3d_texture_add_dirty_region(ptr long ptr)
+@ cdecl wined3d_texture_blt(ptr long ptr ptr long ptr long ptr long)
 @ cdecl wined3d_texture_create(ptr ptr long long ptr ptr ptr ptr)
 @ cdecl wined3d_texture_decref(ptr)
 @ cdecl wined3d_texture_generate_mipmaps(ptr)
 @ cdecl wined3d_texture_get_autogen_filter_type(ptr)
+@ cdecl wined3d_texture_get_dc(ptr long ptr)
 @ cdecl wined3d_texture_get_level_count(ptr)
 @ cdecl wined3d_texture_get_lod(ptr)
 @ cdecl wined3d_texture_get_parent(ptr)
 @ cdecl wined3d_texture_get_sub_resource(ptr long)
 @ cdecl wined3d_texture_incref(ptr)
 @ cdecl wined3d_texture_preload(ptr)
+@ cdecl wined3d_texture_release_dc(ptr long ptr)
 @ cdecl wined3d_texture_set_autogen_filter_type(ptr long)
 @ cdecl wined3d_texture_set_color_key(ptr long ptr)
 @ cdecl wined3d_texture_set_lod(ptr long)
 @ cdecl wined3d_vertex_declaration_get_parent(ptr)
 @ cdecl wined3d_vertex_declaration_incref(ptr)
 
-@ cdecl wined3d_volume_decref(ptr)
-@ cdecl wined3d_volume_from_resource(ptr)
-@ cdecl wined3d_volume_get_parent(ptr)
-@ cdecl wined3d_volume_get_resource(ptr)
-@ cdecl wined3d_volume_incref(ptr)
-@ cdecl wined3d_volume_map(ptr ptr ptr long)
-@ cdecl wined3d_volume_preload(ptr)
-@ cdecl wined3d_volume_unmap(ptr)
-
 @ cdecl wined3d_dxtn_supported()
 @ cdecl wined3d_dxt1_decode(ptr ptr long long long long long)
 @ cdecl wined3d_dxt1_encode(ptr ptr long long long long long)
index 38c1661..6901a26 100644 (file)
@@ -52,6 +52,7 @@ enum wined3d_gl_extension
     ARB_DRAW_BUFFERS,
     ARB_DRAW_ELEMENTS_BASE_VERTEX,
     ARB_DRAW_INSTANCED,
+    ARB_ES2_COMPATIBILITY,
     ARB_FRAGMENT_PROGRAM,
     ARB_FRAGMENT_SHADER,
     ARB_FRAMEBUFFER_OBJECT,
@@ -166,6 +167,7 @@ enum wined3d_gl_extension
     WINED3D_GL_NORMALIZED_TEXRECT,
     WINED3D_GL_LEGACY_CONTEXT,
     WINED3D_GL_VERSION_2_0,
+    WINED3D_GL_VERSION_3_2,
 
     WINED3D_GL_EXT_COUNT,
 };
index ba78f34..7a82055 100644 (file)
@@ -1,3 +1,28 @@
+#if defined(STAGING_CSMT)
+/*
+ * Direct3D wine internal private include file
+ *
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2002-2003, 2004 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2011, 2013-2014 Stefan Dösinger for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#else  /* STAGING_CSMT */
 /*
  * Direct3D wine internal private include file
  *
@@ -21,6 +46,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+#endif /* STAGING_CSMT */
 
 #ifndef __WINE_WINED3D_PRIVATE_H
 #define __WINE_WINED3D_PRIVATE_H
@@ -136,10 +162,10 @@ static inline struct color_fixup_desc create_complex_fixup_desc(enum complex_fix
 {
     struct color_fixup_desc fixup =
     {
-        0, complex_fixup & (1 << 0) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
-        0, complex_fixup & (1 << 1) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
-        0, complex_fixup & (1 << 2) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
-        0, complex_fixup & (1 << 3) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0u, complex_fixup & (1u << 0) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0u, complex_fixup & (1u << 1) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0u, complex_fixup & (1u << 2) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0u, complex_fixup & (1u << 3) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
     };
     return fixup;
 }
@@ -154,6 +180,11 @@ static inline BOOL is_complex_fixup(struct color_fixup_desc fixup)
     return fixup.x_source == CHANNEL_SOURCE_COMPLEX0 || fixup.x_source == CHANNEL_SOURCE_COMPLEX1;
 }
 
+static inline BOOL is_scaling_fixup(struct color_fixup_desc fixup)
+{
+    return fixup.x_sign_fixup || fixup.y_sign_fixup || fixup.z_sign_fixup || fixup.w_sign_fixup;
+}
+
 static inline BOOL is_same_fixup(struct color_fixup_desc f1, struct color_fixup_desc f2)
 {
     return f1.x_sign_fixup == f2.x_sign_fixup && f1.x_source == f2.x_source
@@ -165,10 +196,10 @@ static inline BOOL is_same_fixup(struct color_fixup_desc f1, struct color_fixup_
 static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup)
 {
     enum complex_fixup complex_fixup = 0;
-    if (fixup.x_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 0);
-    if (fixup.y_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 1);
-    if (fixup.z_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 2);
-    if (fixup.w_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 3);
+    if (fixup.x_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1u << 0);
+    if (fixup.y_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1u << 1);
+    if (fixup.z_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1u << 2);
+    if (fixup.w_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1u << 3);
     return complex_fixup;
 }
 
@@ -223,9 +254,9 @@ static inline GLenum wined3d_gl_min_mip_filter(enum wined3d_texture_filter_type
  */
 static inline float float_16_to_32(const unsigned short *in)
 {
-    const unsigned short s = ((*in) & 0x8000);
-    const unsigned short e = ((*in) & 0x7c00) >> 10;
-    const unsigned short m = (*in) & 0x3ff;
+    const unsigned short s = ((*in) & 0x8000u);
+    const unsigned short e = ((*in) & 0x7c00u) >> 10;
+    const unsigned short m = (*in) & 0x3ffu;
     const float sgn = (s ? -1.0f : 1.0f);
 
     if(e == 0) {
@@ -241,9 +272,9 @@ static inline float float_16_to_32(const unsigned short *in)
 
 static inline float float_24_to_32(DWORD in)
 {
-    const float sgn = in & 0x800000 ? -1.0f : 1.0f;
-    const unsigned short e = (in & 0x780000) >> 19;
-    const unsigned int m = in & 0x7ffff;
+    const float sgn = in & 0x800000u ? -1.0f : 1.0f;
+    const unsigned short e = (in & 0x780000u) >> 19;
+    const unsigned int m = in & 0x7ffffu;
 
     if (e == 0)
     {
@@ -378,7 +409,7 @@ enum wined3d_immconst_type
     WINED3D_IMMCONST_VEC4,
 };
 
-#define WINED3DSP_NOSWIZZLE (0 | (1 << 2) | (2 << 4) | (3 << 6))
+#define WINED3DSP_NOSWIZZLE (0u | (1u << 2) | (2u << 4) | (3u << 6))
 
 enum wined3d_shader_src_modifier
 {
@@ -398,11 +429,11 @@ enum wined3d_shader_src_modifier
     WINED3DSPSM_NOT = 13,
 };
 
-#define WINED3DSP_WRITEMASK_0   0x1 /* .x r */
-#define WINED3DSP_WRITEMASK_1   0x2 /* .y g */
-#define WINED3DSP_WRITEMASK_2   0x4 /* .z b */
-#define WINED3DSP_WRITEMASK_3   0x8 /* .w a */
-#define WINED3DSP_WRITEMASK_ALL 0xf /* all */
+#define WINED3DSP_WRITEMASK_0   0x1u /* .x r */
+#define WINED3DSP_WRITEMASK_1   0x2u /* .y g */
+#define WINED3DSP_WRITEMASK_2   0x4u /* .z b */
+#define WINED3DSP_WRITEMASK_3   0x8u /* .w a */
+#define WINED3DSP_WRITEMASK_ALL 0xfu /* all */
 
 enum wined3d_shader_dst_modifier
 {
@@ -427,11 +458,11 @@ enum wined3d_shader_rel_op
     WINED3D_SHADER_REL_OP_LE = 6,
 };
 
-#define WINED3D_SM1_VS  0xfffe
-#define WINED3D_SM1_PS  0xffff
-#define WINED3D_SM4_PS  0x0000
-#define WINED3D_SM4_VS  0x0001
-#define WINED3D_SM4_GS  0x0002
+#define WINED3D_SM1_VS  0xfffeu
+#define WINED3D_SM1_PS  0xffffu
+#define WINED3D_SM4_PS  0x0000u
+#define WINED3D_SM4_VS  0x0001u
+#define WINED3D_SM4_GS  0x0002u
 
 /* Shader version tokens, and shader end tokens */
 #define WINED3DPS_VERSION(major, minor) ((WINED3D_SM1_PS << 16) | ((major) << 8) | (minor))
@@ -623,24 +654,28 @@ struct wined3d_shader_sampler_map
 struct wined3d_shader_reg_maps
 {
     struct wined3d_shader_version shader_version;
-    BYTE texcoord;                          /* MAX_REG_TEXCRD, 8 */
-    BYTE address;                           /* MAX_REG_ADDR, 1 */
-    WORD labels;                            /* MAX_LABELS, 16 */
-    DWORD temporary;                        /* MAX_REG_TEMP, 32 */
-    DWORD *constf;                          /* pixel, vertex */
-    DWORD texcoord_mask[MAX_REG_TEXCRD];    /* vertex < 3.0 */
-    DWORD input_registers;                  /* max(MAX_REG_INPUT, MAX_ATTRIBS), 32 */
-    DWORD output_registers;                 /* MAX_REG_OUTPUT, 32 */
-    WORD integer_constants;                 /* MAX_CONST_I, 16 */
-    WORD boolean_constants;                 /* MAX_CONST_B, 16 */
-    WORD local_int_consts;                  /* MAX_CONST_I, 16 */
-    WORD local_bool_consts;                 /* MAX_CONST_B, 16 */
+    BYTE texcoord;                                  /* MAX_REG_TEXCRD, 8 */
+    BYTE address;                                   /* MAX_REG_ADDR, 1 */
+    WORD labels;                                    /* MAX_LABELS, 16 */
+    DWORD temporary;                                /* MAX_REG_TEMP, 32 */
+    DWORD *constf;                                  /* pixel, vertex */
+    union
+    {
+        DWORD texcoord_mask[MAX_REG_TEXCRD];        /* vertex < 3.0 */
+        BYTE output_registers_mask[MAX_REG_OUTPUT]; /* vertex >= 3.0 */
+    } u;
+    DWORD input_registers;                          /* max(MAX_REG_INPUT, MAX_ATTRIBS), 32 */
+    DWORD output_registers;                         /* MAX_REG_OUTPUT, 32 */
+    WORD integer_constants;                         /* MAX_CONST_I, 16 */
+    WORD boolean_constants;                         /* MAX_CONST_B, 16 */
+    WORD local_int_consts;                          /* MAX_CONST_I, 16 */
+    WORD local_bool_consts;                         /* MAX_CONST_B, 16 */
     UINT cb_sizes[WINED3D_MAX_CBS];
 
     struct wined3d_shader_resource_info resource_info[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)];
     struct wined3d_shader_sampler_map sampler_map;
-    BYTE bumpmat;                           /* MAX_TEXTURES, 8 */
-    BYTE luminanceparams;                   /* MAX_TEXTURES, 8 */
+    BYTE bumpmat;                                   /* MAX_TEXTURES, 8 */
+    BYTE luminanceparams;                           /* MAX_TEXTURES, 8 */
 
     WORD usesnrm        : 1;
     WORD vpos           : 1;
@@ -788,6 +823,7 @@ struct shader_caps
     DWORD vs_uniform_count;
     DWORD ps_uniform_count;
     float ps_1x_max_value;
+    DWORD varying_count;
 
     DWORD wined3d_caps;
 };
@@ -824,11 +860,11 @@ enum wined3d_ffp_ps_fog_mode
  * into the shader code
  */
 
-#define WINED3D_PSARGS_PROJECTED (1 << 3)
+#define WINED3D_PSARGS_PROJECTED (1u << 3)
 #define WINED3D_PSARGS_TEXTRANSFORM_SHIFT 4
-#define WINED3D_PSARGS_TEXTRANSFORM_MASK 0xf
+#define WINED3D_PSARGS_TEXTRANSFORM_MASK 0xfu
 #define WINED3D_PSARGS_TEXTYPE_SHIFT 2
-#define WINED3D_PSARGS_TEXTYPE_MASK 0x3
+#define WINED3D_PSARGS_TEXTYPE_MASK 0x3u
 
 /* Used for Shader Model 1 pixel shaders to track the bound texture
  * type. 2D and RECT textures are separated through NP2 fixup. */
@@ -846,12 +882,14 @@ struct ps_compile_args {
     WORD                        tex_transform; /* ps 1.0-1.3, 4 textures */
     WORD                        tex_types; /* ps 1.0 - 1.4, 6 textures */
     WORD                        srgb_correction;
-    WORD                        np2_fixup;
     /* Bitmap for NP2 texcoord fixups (16 samplers max currently).
        D3D9 has a limit of 16 samplers and the fixup is superfluous
        in D3D10 (unconditional NP2 support mandatory). */
+    WORD                        np2_fixup;
     WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */
+    WORD texcoords_initialized; /* MAX_TEXTURES, 8 */
     BOOL pointsprite;
+    BOOL flatshading;
 };
 
 enum fog_src_type {
@@ -865,7 +903,8 @@ struct vs_compile_args
     BYTE clip_enabled : 1;
     BYTE point_size : 1;
     BYTE per_vertex_point_size : 1;
-    BYTE padding : 5;
+    BYTE flatshading : 1;
+    BYTE padding : 4;
     WORD swizzle_map;   /* MAX_ATTRIBS, 16 */
 };
 
@@ -1354,10 +1393,14 @@ struct fragment_caps
     DWORD MaxSimultaneousTextures;
 };
 
+#define GL_EXT_EMUL_ARB_MULTITEXTURE 0x00000001
+#define GL_EXT_EMUL_EXT_FOG_COORD    0x00000002
+
 struct fragment_pipeline
 {
     void (*enable_extension)(const struct wined3d_gl_info *gl_info, BOOL enable);
     void (*get_caps)(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps);
+    DWORD (*get_emul_mask)(const struct wined3d_gl_info *gl_info);
     void *(*alloc_private)(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv);
     void (*free_private)(struct wined3d_device *device);
     BOOL (*allocate_context_data)(struct wined3d_context *context);
@@ -1369,6 +1412,7 @@ struct fragment_pipeline
 struct wined3d_vertex_caps
 {
     BOOL xyzrhw;
+    BOOL emulated_flatshading;
     BOOL ffp_generic_attributes;
     DWORD max_active_lights;
     DWORD max_vertex_blend_matrices;
@@ -1383,6 +1427,7 @@ struct wined3d_vertex_pipe_ops
 {
     void (*vp_enable)(const struct wined3d_gl_info *gl_info, BOOL enable);
     void (*vp_get_caps)(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps);
+    DWORD (*vp_get_emul_mask)(const struct wined3d_gl_info *gl_info);
     void *(*vp_alloc)(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv);
     void (*vp_free)(struct wined3d_device *device);
     const struct StateEntryTemplate *vp_states;
@@ -1484,6 +1529,7 @@ void context_resource_released(const struct wined3d_device *device,
         struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
 void context_resource_unloaded(const struct wined3d_device *device,
         struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
+void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) DECLSPEC_HIDDEN;
 BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
 void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
@@ -1553,6 +1599,7 @@ enum wined3d_pci_device
     CARD_AMD_RADEON_HD2600          = 0x9581,
     CARD_AMD_RADEON_HD2900          = 0x9400,
     CARD_AMD_RADEON_HD3200          = 0x9620,
+    CARD_AMD_RADEON_HD3850          = 0x9515,
     CARD_AMD_RADEON_HD4200M         = 0x9712,
     CARD_AMD_RADEON_HD4350          = 0x954f,
     CARD_AMD_RADEON_HD4600          = 0x9495,
@@ -1631,6 +1678,7 @@ enum wined3d_pci_device
     CARD_NVIDIA_GEFORCE_GTS350M     = 0x0cb0,
     CARD_NVIDIA_GEFORCE_410M        = 0x1055,
     CARD_NVIDIA_GEFORCE_GT420       = 0x0de2,
+    CARD_NVIDIA_GEFORCE_GT425M      = 0x0df0,
     CARD_NVIDIA_GEFORCE_GT430       = 0x0de1,
     CARD_NVIDIA_GEFORCE_GT440       = 0x0de0,
     CARD_NVIDIA_GEFORCE_GTS450      = 0x0dc4,
@@ -1790,6 +1838,7 @@ struct wined3d_gl_info
     DWORD quirks;
     BOOL supported[WINED3D_GL_EXT_COUNT];
     GLint wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP + 1];
+    float fixed_polyoffset_scale, float_polyoffset_scale;
 
     HGLRC (WINAPI *p_wglCreateContextAttribsARB)(HDC dc, HGLRC share, const GLint *attribs);
     struct opengl_funcs gl_ops;
@@ -1814,6 +1863,7 @@ struct wined3d_d3d_limits
     UINT vs_version, gs_version, ps_version;
     DWORD vs_uniform_count;
     DWORD ps_uniform_count;
+    UINT varying_count;
     UINT ffp_textures;
     UINT ffp_blend_stages;
     UINT ffp_vertex_blend_matrices;
@@ -1837,6 +1887,7 @@ struct wined3d_d3d_info
     struct wined3d_d3d_limits limits;
     struct wined3d_ffp_attrib_ops ffp_attrib_ops;
     BOOL xyzrhw;
+    BOOL emulated_flatshading;
     BOOL ffp_generic_attributes;
     BOOL vs_clipping;
     BOOL shader_color_key;
@@ -1866,11 +1917,26 @@ struct wined3d_adapter
     const struct blit_shader *blitter;
 };
 
-BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN;
+struct wined3d_caps_gl_ctx
+{
+    HDC dc;
+    HWND wnd;
+    HGLRC gl_ctx;
+    HDC restore_dc;
+    HGLRC restore_gl_ctx;
+
+    const struct wined3d_gl_info *gl_info;
+    GLuint test_vbo;
+    GLuint test_program_id;
+};
+
+float wined3d_adapter_find_polyoffset_scale(struct wined3d_caps_gl_ctx *ctx, GLenum format) DECLSPEC_HIDDEN;
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter,
+        struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN;
 UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) DECLSPEC_HIDDEN;
 
 BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
-extern void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN;
 
 enum projection_types
 {
@@ -1914,8 +1980,11 @@ struct ffp_frag_settings
     enum wined3d_ffp_ps_fog_mode fog;
     unsigned char sRGB_write;
     unsigned char emul_clipplanes;
-    unsigned char color_key_enabled;
-    unsigned char padding;
+    unsigned char texcoords_initialized;
+    unsigned char color_key_enabled : 1;
+    unsigned char pointsprite : 1;
+    unsigned char flatshading : 1;
+    unsigned char padding : 5;
 };
 
 struct ffp_frag_desc
@@ -1928,6 +1997,7 @@ extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECL
 extern const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions DECLSPEC_HIDDEN;
 extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN;
 
+unsigned int wined3d_max_compat_varyings(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
         struct ffp_frag_settings *settings, BOOL ignore_textype) DECLSPEC_HIDDEN;
 const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
@@ -1948,10 +2018,10 @@ enum wined3d_ffp_vs_fog_mode
 };
 
 #define WINED3D_FFP_TCI_SHIFT               16
-#define WINED3D_FFP_TCI_MASK                0xff
+#define WINED3D_FFP_TCI_MASK                0xffu
 
 #define WINED3D_FFP_LIGHT_TYPE_SHIFT(idx)   (3 * (idx))
-#define WINED3D_FFP_LIGHT_TYPE_MASK         0x7
+#define WINED3D_FFP_LIGHT_TYPE_MASK         0x7u
 
 struct wined3d_ffp_vs_settings
 {
@@ -1973,7 +2043,8 @@ struct wined3d_ffp_vs_settings
     DWORD fog_mode        : 2;
     DWORD texcoords       : 8;  /* MAX_TEXTURES */
     DWORD ortho_fog       : 1;
-    DWORD padding         : 11;
+    DWORD flatshading     : 1;
+    DWORD padding         : 10;
 
     DWORD texgen[MAX_TEXTURES];
 };
@@ -1984,8 +2055,8 @@ struct wined3d_ffp_vs_desc
     struct wined3d_ffp_vs_settings settings;
 };
 
-void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
-        struct wined3d_ffp_vs_settings *settings) DECLSPEC_HIDDEN;
+void wined3d_ffp_get_vs_settings(const struct wined3d_context *context,
+        const struct wined3d_state *state, struct wined3d_ffp_vs_settings *settings) DECLSPEC_HIDDEN;
 
 struct wined3d
 {
@@ -2217,7 +2288,7 @@ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD sta
 {
     DWORD idx = state / (sizeof(*context->isStateDirty) * CHAR_BIT);
     BYTE shift = state & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
-    return context->isStateDirty[idx] & (1 << shift);
+    return context->isStateDirty[idx] & (1u << shift);
 }
 
 #define WINED3D_RESOURCE_ACCESS_GPU     0x1
@@ -2228,6 +2299,9 @@ struct wined3d_resource_ops
     ULONG (*resource_incref)(struct wined3d_resource *resource);
     ULONG (*resource_decref)(struct wined3d_resource *resource);
     void (*resource_unload)(struct wined3d_resource *resource);
+    HRESULT (*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);
+    HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx);
 #if defined(STAGING_CSMT)
     void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location);
     void (*resource_load_location)(struct wined3d_resource *resource,
@@ -2267,7 +2341,6 @@ struct wined3d_resource
     BOOL unmap_dirtify;
 #else  /* STAGING_CSMT */
     void *heap_memory;
-    UINT custom_row_pitch, custom_slice_pitch;
     struct list resource_list_entry;
 #endif /* STAGING_CSMT */
 
@@ -2308,6 +2381,8 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource,
         const struct wined3d_context *context, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_resource_get_memory(const struct wined3d_resource *resource,
         DWORD location, struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
+void wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch,
+        UINT *slice_pitch) DECLSPEC_HIDDEN;
 GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
 void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN;
 BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
@@ -2493,6 +2568,9 @@ HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wi
 void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
 void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context,
         BOOL srgb_mode) DECLSPEC_HIDDEN;
+HRESULT wined3d_volume_map(struct wined3d_volume *volume,
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN;
+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
         const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
 void wined3d_volume_cleanup_cs(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
@@ -2505,10 +2583,14 @@ BOOL volume_prepare_system_memory(struct wined3d_volume *volume) DECLSPEC_HIDDEN
 HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
         unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN;
 void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) DECLSPEC_HIDDEN;
 void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context,
         BOOL srgb_mode) DECLSPEC_HIDDEN;
 void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN;
+HRESULT wined3d_volume_map(struct wined3d_volume *volume,
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN;
+HRESULT wined3d_volume_unmap(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
         const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
 
@@ -2567,6 +2649,7 @@ struct wined3d_surface
 
     DWORD flags;
 
+    UINT pitch;
     UINT pow2Width;
     UINT pow2Height;
 
@@ -2620,14 +2703,17 @@ void surface_get_drawable_size(const struct wined3d_surface *surface, const stru
 void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
 void surface_load_ds_location(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
-void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
 #else  /* STAGING_CSMT */
 void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN;
-void surface_load(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
+void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
 void surface_load_ds_location(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
-void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
-HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN;
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
+HRESULT surface_load_location(struct wined3d_surface *surface,
+        struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 #endif /* STAGING_CSMT */
 void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN;
 void surface_prepare_rb(struct wined3d_surface *surface,
@@ -2651,14 +2737,10 @@ void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct w
 void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
         struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
         const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN;
+BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN;
 void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void wined3d_surface_getdc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void wined3d_surface_releasedc_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
-
-void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
-        const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-void surface_flip(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN;
 #else  /* STAGING_CSMT */
 void surface_validate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN;
 HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
@@ -2669,11 +2751,10 @@ void surface_prepare_map_memory(struct wined3d_surface *surface) DECLSPEC_HIDDEN
 void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
         const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
         BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
+#endif /* STAGING_CSMT */
 
 void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
         const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN;
-#endif /* STAGING_CSMT */
 
 /* Surface flags: */
 #define SFLAG_DIBSECTION        0x00000001 /* Has a DIB section attached for GetDC. */
@@ -2693,6 +2774,10 @@ struct wined3d_sampler
     GLuint name;
 };
 
+#if defined(STAGING_CSMT)
+void wined3d_sampler_destroy(struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
+
+#endif /* STAGING_CSMT */
 struct wined3d_vertex_declaration_element
 {
     const struct wined3d_format *format;
@@ -2978,6 +3063,10 @@ void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_getdc(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_releasedc(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_sampler_destroy(struct wined3d_cs *cs, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
+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) DECLSPEC_HIDDEN;
 #endif /* STAGING_CSMT */
 
 /* Direct3D terminology with little modifications. We do not have an issued state
@@ -3182,7 +3271,6 @@ struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchai
 void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
-void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 #if defined(STAGING_CSMT)
 HRESULT swapchain_create_context_cs(struct wined3d_device *device,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
@@ -3250,11 +3338,9 @@ void state_pointsprite_w(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 void state_pointsprite(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_shademode(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 
-BOOL getColorBits(const struct wined3d_format *format,
-        BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize) DECLSPEC_HIDDEN;
-BOOL getDepthStencilBits(const struct wined3d_format *format,
-        BYTE *depthSize, BYTE *stencilSize) DECLSPEC_HIDDEN;
 GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN;
 
 /* Math utils */
@@ -3373,10 +3459,11 @@ struct wined3d_shader
 void pixelshader_update_resource_types(struct wined3d_shader *shader, WORD tex_types) DECLSPEC_HIDDEN;
 void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
         BOOL position_transformed, struct ps_compile_args *args,
-        const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+        const struct wined3d_context *context) DECLSPEC_HIDDEN;
 
 void find_vs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
-        WORD swizzle_map, struct vs_compile_args *args) DECLSPEC_HIDDEN;
+        WORD swizzle_map, struct vs_compile_args *args,
+        const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN;
 
 void string_buffer_clear(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
 BOOL string_buffer_init(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
@@ -3500,6 +3587,9 @@ struct ps_np2fixup_info {
     WORD              num_consts;
 };
 
+void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program) DECLSPEC_HIDDEN;
+void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program) DECLSPEC_HIDDEN;
+
 struct wined3d_palette
 {
     LONG ref;
@@ -3601,6 +3691,8 @@ DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface,
         const struct wined3d_color *color) DECLSPEC_HIDDEN;
 BOOL wined3d_format_convert_color_to_float(const struct wined3d_format *format,
         const struct wined3d_palette *palette, DWORD color, struct wined3d_color *float_color) DECLSPEC_HIDDEN;
+void wined3d_format_get_float_color_key(const struct wined3d_format *format,
+        const struct wined3d_color_key *key, struct wined3d_color *float_colors) DECLSPEC_HIDDEN;
 const struct wined3d_color_key_conversion * wined3d_format_get_color_key_conversion(
         const struct wined3d_texture *texture, BOOL need_alpha_ck) DECLSPEC_HIDDEN;
 
@@ -3630,6 +3722,6 @@ void wined3d_dxtn_free(void) DECLSPEC_HIDDEN;
 /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
 #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
 
-#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffff) << 16) | (min & 0xffff))
+#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffffu) << 16) | (min & 0xffffu))
 
 #endif
index 0a1065c..a44442b 100644 (file)
@@ -496,8 +496,8 @@ __CRT_UUID_DECL(IDirect3DSwapChain9Ex,        0x91886caf, 0x1c3d, 0x4d2e, 0xa0,
 /*** IDirect3DSwapChain9 methods ***/
 #define IDirect3DSwapChain9Ex_Present(p,a,b,c,d,e)       (p)->lpVtbl->Present(p,a,b,c,d,e)
 #define IDirect3DSwapChain9Ex_GetFrontBufferData(p,a)    (p)->lpVtbl->GetFrontBufferData(p,a)
-#define IDirect3DSwapChain9EX_GetBackBuffer(p,a,b,c)     (p)->lpVtbl->GetBackBuffer(p,a,b,c)
-#define IDirect3DSwapChain9EX_GetRasterStatus(p,a)       (p)->lpVtbl->GetRasterStatus(p,a)
+#define IDirect3DSwapChain9Ex_GetBackBuffer(p,a,b,c)     (p)->lpVtbl->GetBackBuffer(p,a,b,c)
+#define IDirect3DSwapChain9Ex_GetRasterStatus(p,a)       (p)->lpVtbl->GetRasterStatus(p,a)
 #define IDirect3DSwapChain9Ex_GetDisplayMode(p,a)        (p)->lpVtbl->GetDisplayMode(p,a)
 #define IDirect3DSwapChain9Ex_GetDevice(p,a)             (p)->lpVtbl->GetDevice(p,a)
 #define IDirect3DSwapChain9Ex_GetPresentParameters(p,a)  (p)->lpVtbl->GetPresentParameters(p,a)
index 27e8ff3..77e7671 100644 (file)
@@ -503,13 +503,6 @@ enum wined3d_patch_edge_style
     WINED3D_PATCH_EDGE_CONTINUOUS           = 1,
 };
 
-enum wined3d_backbuffer_type
-{
-    WINED3D_BACKBUFFER_TYPE_MONO            = 0,
-    WINED3D_BACKBUFFER_TYPE_LEFT            = 1,
-    WINED3D_BACKBUFFER_TYPE_RIGHT           = 2,
-};
-
 enum wined3d_swap_effect
 {
     WINED3D_SWAP_EFFECT_DISCARD             = 1,
@@ -724,9 +717,9 @@ struct wined3d_query_data_timestamp_disjoint
     BOOL disjoint;
 };
 
-#define WINED3DISSUE_BEGIN                                      (1 << 1)
-#define WINED3DISSUE_END                                        (1 << 0)
-#define WINED3DGETDATA_FLUSH                                    (1 << 0)
+#define WINED3DISSUE_BEGIN                                      (1u << 1)
+#define WINED3DISSUE_END                                        (1u << 0)
+#define WINED3DGETDATA_FLUSH                                    (1u << 0)
 
 enum wined3d_stateblock_type
 {
@@ -797,14 +790,13 @@ enum wined3d_display_rotation
     WINED3D_DISPLAY_ROTATION_270            = 4,
 };
 
-#define WINED3DCOLORWRITEENABLE_RED                             (1 << 0)
-#define WINED3DCOLORWRITEENABLE_GREEN                           (1 << 1)
-#define WINED3DCOLORWRITEENABLE_BLUE                            (1 << 2)
-#define WINED3DCOLORWRITEENABLE_ALPHA                           (1 << 3)
+#define WINED3DCOLORWRITEENABLE_RED                             (1u << 0)
+#define WINED3DCOLORWRITEENABLE_GREEN                           (1u << 1)
+#define WINED3DCOLORWRITEENABLE_BLUE                            (1u << 2)
+#define WINED3DCOLORWRITEENABLE_ALPHA                           (1u << 3)
 
 #define WINED3DADAPTER_DEFAULT                                  0
 #define WINED3DENUM_NO_WHQL_LEVEL                               2
-#define WINED3DPRESENT_BACK_BUFFER_MAX                          3
 
 #define WINED3DTSS_TCI_PASSTHRU                                 0x00000
 #define WINED3DTSS_TCI_CAMERASPACENORMAL                        0x10000
@@ -875,12 +867,12 @@ enum wined3d_display_rotation
 #define WINED3DPRESENT_INTERVAL_IMMEDIATE                       0x80000000
 
 #define WINED3DMAXUSERCLIPPLANES                                32
-#define WINED3DCLIPPLANE0                                       (1 << 0)
-#define WINED3DCLIPPLANE1                                       (1 << 1)
-#define WINED3DCLIPPLANE2                                       (1 << 2)
-#define WINED3DCLIPPLANE3                                       (1 << 3)
-#define WINED3DCLIPPLANE4                                       (1 << 4)
-#define WINED3DCLIPPLANE5                                       (1 << 5)
+#define WINED3DCLIPPLANE0                                       (1u << 0)
+#define WINED3DCLIPPLANE1                                       (1u << 1)
+#define WINED3DCLIPPLANE2                                       (1u << 2)
+#define WINED3DCLIPPLANE3                                       (1u << 3)
+#define WINED3DCLIPPLANE4                                       (1u << 4)
+#define WINED3DCLIPPLANE5                                       (1u << 5)
 
 /* FVF (Flexible Vertex Format) codes */
 #define WINED3DFVF_RESERVED0                                    0x0001
@@ -912,10 +904,10 @@ enum wined3d_display_rotation
 #define WINED3DFVF_LASTBETA_D3DCOLOR                            0x8000
 #define WINED3DFVF_RESERVED2                                    0x6000
 
-#define WINED3DFVF_TEXTUREFORMAT1                               3
-#define WINED3DFVF_TEXTUREFORMAT2                               0
-#define WINED3DFVF_TEXTUREFORMAT3                               1
-#define WINED3DFVF_TEXTUREFORMAT4                               2
+#define WINED3DFVF_TEXTUREFORMAT1                               3u
+#define WINED3DFVF_TEXTUREFORMAT2                               0u
+#define WINED3DFVF_TEXTUREFORMAT3                               1u
+#define WINED3DFVF_TEXTUREFORMAT4                               2u
 #define WINED3DFVF_TEXCOORDSIZE1(idx)                           (WINED3DFVF_TEXTUREFORMAT1 << (idx * 2 + 16))
 #define WINED3DFVF_TEXCOORDSIZE2(idx)                           (WINED3DFVF_TEXTUREFORMAT2 << (idx * 2 + 16))
 #define WINED3DFVF_TEXCOORDSIZE3(idx)                           (WINED3DFVF_TEXTUREFORMAT3 << (idx * 2 + 16))
@@ -927,8 +919,8 @@ enum wined3d_display_rotation
 #define WINED3DCLEAR_STENCIL                                    0x00000004
 
 /* Stream source flags */
-#define WINED3DSTREAMSOURCE_INDEXEDDATA                         (1 << 30)
-#define WINED3DSTREAMSOURCE_INSTANCEDATA                        (2 << 30)
+#define WINED3DSTREAMSOURCE_INDEXEDDATA                         (1u << 30)
+#define WINED3DSTREAMSOURCE_INSTANCEDATA                        (2u << 30)
 
 /* SetPrivateData flags */
 #define WINED3DSPD_IUNKNOWN                                     0x00000001
@@ -1252,7 +1244,6 @@ enum wined3d_display_rotation
 
 #define WINED3D_RESZ_CODE                                       0x7fa05000
 
-#define WINED3D_CKEY_COLORSPACE                                 0x00000001
 #define WINED3D_CKEY_DST_BLT                                    0x00000002
 #define WINED3D_CKEY_DST_OVERLAY                                0x00000004
 #define WINED3D_CKEY_SRC_BLT                                    0x00000008
@@ -2027,7 +2018,6 @@ struct wined3d_surface;
 struct wined3d_swapchain;
 struct wined3d_texture;
 struct wined3d_vertex_declaration;
-struct wined3d_volume;
 
 struct wined3d_device_parent
 {
@@ -2039,12 +2029,14 @@ struct wined3d_device_parent_ops
     void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device);
     void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent);
     void (__cdecl *activate)(struct wined3d_device_parent *device_parent, BOOL activate);
-    HRESULT (__cdecl *surface_created)(struct wined3d_device_parent *device_parent, void *container_parent,
+    HRESULT (__cdecl *surface_created)(struct wined3d_device_parent *device_parent,
+            struct wined3d_texture *texture, unsigned int sub_resource_idx,
             struct wined3d_surface *surface, void **parent, const struct wined3d_parent_ops **parent_ops);
-    HRESULT (__cdecl *volume_created)(struct wined3d_device_parent *device_parent, void *container_parent,
-            struct wined3d_volume *volume, void **parent, const struct wined3d_parent_ops **parent_ops);
-    HRESULT (__cdecl *create_swapchain_surface)(struct wined3d_device_parent *device_parent, void *container_parent,
-            const struct wined3d_resource_desc *desc, struct wined3d_surface **surface);
+    HRESULT (__cdecl *volume_created)(struct wined3d_device_parent *device_parent,
+            struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+            void **parent, const struct wined3d_parent_ops **parent_ops);
+    HRESULT (__cdecl *create_swapchain_texture)(struct wined3d_device_parent *device_parent, void *parent,
+            const struct wined3d_resource_desc *desc, struct wined3d_texture **texture);
     HRESULT (__cdecl *create_swapchain)(struct wined3d_device_parent *device_parent,
             struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain);
 };
@@ -2113,7 +2105,8 @@ HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d,
         UINT adapter_idx, const struct wined3d_display_mode *mode);
 
 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);
 HRESULT __cdecl wined3d_buffer_create_ib(struct wined3d_device *device, UINT length, DWORD usage,
         enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_buffer **buffer);
@@ -2137,6 +2130,10 @@ HRESULT __cdecl wined3d_device_clear_rendertarget_view(struct wined3d_device *de
         struct wined3d_rendertarget_view *view, const RECT *rect, const struct wined3d_color *color);
 void __cdecl wined3d_device_copy_resource(struct wined3d_device *device,
         struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource);
+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);
 HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx,
         enum wined3d_device_type device_type, HWND focus_window, DWORD behaviour_flags, BYTE surface_alignment,
         struct wined3d_device_parent *device_parent, struct wined3d_device **device);
@@ -2151,8 +2148,6 @@ HRESULT __cdecl wined3d_device_end_scene(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_end_stateblock(struct wined3d_device *device, struct wined3d_stateblock **stateblock);
 void __cdecl wined3d_device_evict_managed_resources(struct wined3d_device *device);
 UINT __cdecl wined3d_device_get_available_texture_mem(const struct wined3d_device *device);
-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);
 INT __cdecl wined3d_device_get_base_vertex_index(const struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_get_clip_plane(const struct wined3d_device *device,
         UINT plane_idx, struct wined3d_vec4 *plane);
@@ -2164,8 +2159,6 @@ struct wined3d_rendertarget_view * __cdecl wined3d_device_get_depth_stencil_view
 HRESULT __cdecl wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps);
 HRESULT __cdecl wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx,
         struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);
-HRESULT __cdecl wined3d_device_get_front_buffer_data(const struct wined3d_device *device,
-        UINT swapchain_idx, struct wined3d_surface *dst_surface);
 void __cdecl wined3d_device_get_gamma_ramp(const struct wined3d_device *device,
         UINT swapchain_idx, struct wined3d_gamma_ramp *ramp);
 struct wined3d_shader * __cdecl wined3d_device_get_geometry_shader(const struct wined3d_device *device);
@@ -2236,8 +2229,6 @@ HRESULT __cdecl wined3d_device_init_3d(struct wined3d_device *device, struct win
 HRESULT __cdecl wined3d_device_init_gdi(struct wined3d_device *device, struct wined3d_swapchain_desc *swapchain_desc);
 void __cdecl wined3d_device_multiply_transform(struct wined3d_device *device,
         enum wined3d_transform_state state, const struct wined3d_matrix *matrix);
-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);
 HRESULT __cdecl wined3d_device_process_vertices(struct wined3d_device *device,
         UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
         const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf);
@@ -2254,7 +2245,7 @@ HRESULT __cdecl wined3d_device_set_clip_status(struct wined3d_device *device,
 void __cdecl wined3d_device_set_cursor_position(struct wined3d_device *device,
         int x_screen_space, int y_screen_space, DWORD flags);
 HRESULT __cdecl wined3d_device_set_cursor_properties(struct wined3d_device *device,
-        UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_surface);
+        UINT x_hotspot, UINT y_hotspot, struct wined3d_texture *texture, unsigned int sub_resource_idx);
 void __cdecl wined3d_device_set_depth_stencil_view(struct wined3d_device *device,
         struct wined3d_rendertarget_view *view);
 HRESULT __cdecl wined3d_device_set_dialog_box_mode(struct wined3d_device *device, BOOL enable_dialogs);
@@ -2324,6 +2315,9 @@ void __cdecl wined3d_device_setup_fullscreen_window(struct wined3d_device *devic
 BOOL __cdecl wined3d_device_show_cursor(struct wined3d_device *device, BOOL show);
 HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device);
+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);
 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);
 HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device,
@@ -2427,17 +2421,21 @@ static inline HRESULT wined3d_private_store_set_private_data(struct wined3d_priv
 void __cdecl wined3d_resource_get_desc(const struct wined3d_resource *resource,
         struct wined3d_resource_desc *desc);
 void * __cdecl wined3d_resource_get_parent(const struct wined3d_resource *resource);
-void __cdecl wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch,
-        UINT *slice_pitch);
 DWORD __cdecl wined3d_resource_get_priority(const struct wined3d_resource *resource);
 void __cdecl wined3d_resource_set_parent(struct wined3d_resource *resource, void *parent);
 DWORD __cdecl wined3d_resource_set_priority(struct wined3d_resource *resource, DWORD priority);
+HRESULT __cdecl wined3d_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);
+HRESULT __cdecl wined3d_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx);
 
 HRESULT __cdecl wined3d_rendertarget_view_create(const struct wined3d_rendertarget_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_rendertarget_view **view);
 HRESULT __cdecl wined3d_rendertarget_view_create_from_surface(struct wined3d_surface *surface,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view);
+HRESULT __cdecl wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_rendertarget_view **view);
 ULONG __cdecl wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view);
 void * __cdecl wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view);
 struct wined3d_resource * __cdecl wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view);
@@ -2483,18 +2481,15 @@ HRESULT __cdecl wined3d_surface_blt(struct wined3d_surface *dst_surface, const R
         const WINEDDBLTFX *blt_fx, enum wined3d_texture_filter_type filter);
 ULONG __cdecl wined3d_surface_decref(struct wined3d_surface *surface);
 struct wined3d_surface * __cdecl wined3d_surface_from_resource(struct wined3d_resource *resource);
-HRESULT __cdecl wined3d_surface_get_blt_status(const struct wined3d_surface *surface, DWORD flags);
-HRESULT __cdecl wined3d_surface_get_flip_status(const struct wined3d_surface *surface, DWORD flags);
 HRESULT __cdecl wined3d_surface_get_overlay_position(const struct wined3d_surface *surface, LONG *x, LONG *y);
 void * __cdecl wined3d_surface_get_parent(const struct wined3d_surface *surface);
-HRESULT __cdecl wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
-        struct wined3d_surface *render_target);
+DWORD __cdecl wined3d_surface_get_pitch(const struct wined3d_surface *surface);
 struct wined3d_resource * __cdecl wined3d_surface_get_resource(struct wined3d_surface *surface);
 HRESULT __cdecl wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc);
 ULONG __cdecl wined3d_surface_incref(struct wined3d_surface *surface);
 HRESULT __cdecl wined3d_surface_is_lost(const struct wined3d_surface *surface);
 HRESULT __cdecl wined3d_surface_map(struct wined3d_surface *surface,
-        struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags);
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags);
 void __cdecl wined3d_surface_preload(struct wined3d_surface *surface);
 HRESULT __cdecl wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc);
 HRESULT __cdecl wined3d_surface_restore(struct wined3d_surface *surface);
@@ -2508,13 +2503,13 @@ HRESULT __cdecl wined3d_surface_update_overlay_z_order(struct wined3d_surface *s
 HRESULT __cdecl wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
 ULONG __cdecl wined3d_swapchain_decref(struct wined3d_swapchain *swapchain);
-struct wined3d_surface * __cdecl wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
-        UINT backbuffer_idx, enum wined3d_backbuffer_type backbuffer_type);
+struct wined3d_texture * __cdecl wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
+        UINT backbuffer_idx);
 struct wined3d_device * __cdecl wined3d_swapchain_get_device(const struct wined3d_swapchain *swapchain);
 HRESULT __cdecl wined3d_swapchain_get_display_mode(const struct wined3d_swapchain *swapchain,
         struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);
 HRESULT __cdecl wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain,
-        struct wined3d_surface *dst_surface);
+        struct wined3d_texture *dst_texture, unsigned int sub_resource_idx);
 HRESULT __cdecl wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *swapchain,
         struct wined3d_gamma_ramp *ramp);
 void * __cdecl wined3d_swapchain_get_parent(const struct wined3d_swapchain *swapchain);
@@ -2526,6 +2521,9 @@ ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain);
 HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
         const RGNDATA *dirty_region, DWORD flags);
+HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
+        unsigned int width, unsigned int height, enum wined3d_format_id format_id,
+        enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);
 HRESULT __cdecl wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain,
         DWORD flags, const struct wined3d_gamma_ramp *ramp);
 void __cdecl wined3d_swapchain_set_palette(struct wined3d_swapchain *swapchain, struct wined3d_palette *palette);
@@ -2533,12 +2531,16 @@ void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, H
 
 HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
         UINT layer, const struct wined3d_box *dirty_region);
+HRESULT __cdecl wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_idx, const RECT *dst_rect_in,
+        struct wined3d_texture *src_texture, unsigned int src_idx, const RECT *src_rect_in, DWORD flags,
+        const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter);
 HRESULT __cdecl wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
         UINT level_count, DWORD surface_flags, const struct wined3d_sub_resource_data *data, void *parent,
         const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
 ULONG __cdecl wined3d_texture_decref(struct wined3d_texture *texture);
 void __cdecl wined3d_texture_generate_mipmaps(struct wined3d_texture *texture);
 enum wined3d_texture_filter_type __cdecl wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture);
+HRESULT __cdecl wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc);
 DWORD __cdecl wined3d_texture_get_level_count(const struct wined3d_texture *texture);
 DWORD __cdecl wined3d_texture_get_lod(const struct wined3d_texture *texture);
 void * __cdecl wined3d_texture_get_parent(const struct wined3d_texture *texture);
@@ -2552,6 +2554,7 @@ HRESULT __cdecl wined3d_texture_set_autogen_filter_type(struct wined3d_texture *
 HRESULT __cdecl wined3d_texture_set_color_key(struct wined3d_texture *texture,
         DWORD flags, const struct wined3d_color_key *color_key);
 DWORD __cdecl wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod);
+HRESULT __cdecl wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc);
 HRESULT __cdecl wined3d_texture_update_desc(struct wined3d_texture *texture,
         UINT width, UINT height, enum wined3d_format_id format_id,
         enum wined3d_multisample_type multisample_type, UINT multisample_quality,
@@ -2567,16 +2570,6 @@ ULONG __cdecl wined3d_vertex_declaration_decref(struct wined3d_vertex_declaratio
 void * __cdecl wined3d_vertex_declaration_get_parent(const struct wined3d_vertex_declaration *declaration);
 ULONG __cdecl wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration *declaration);
 
-ULONG __cdecl wined3d_volume_decref(struct wined3d_volume *volume);
-struct wined3d_volume * __cdecl wined3d_volume_from_resource(struct wined3d_resource *resource);
-void * __cdecl wined3d_volume_get_parent(const struct wined3d_volume *volume);
-struct wined3d_resource * __cdecl wined3d_volume_get_resource(struct wined3d_volume *volume);
-ULONG __cdecl wined3d_volume_incref(struct wined3d_volume *volume);
-HRESULT __cdecl wined3d_volume_map(struct wined3d_volume *volume,
-        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags);
-void __cdecl wined3d_volume_preload(struct wined3d_volume *volume);
-HRESULT __cdecl wined3d_volume_unmap(struct wined3d_volume *volume);
-
 /* Return the integer base-2 logarithm of x. Undefined for x == 0. */
 static inline unsigned int wined3d_log2i(unsigned int x)
 {
index a8841f1..9429aa8 100644 (file)
@@ -22,13 +22,13 @@ reactos/tools/wpp                 # Synced to WineStaging-1.7.47
 The following libraries are shared with Wine.
 
 reactos/dll/directx/wine/amstream       # Synced to WineStaging-1.7.55
-reactos/dll/directx/wine/d3d8           # Synced to WineStaging-1.7.47
-reactos/dll/directx/wine/d3d9           # Synced to WineStaging-1.7.47
+reactos/dll/directx/wine/d3d8           # Synced to WineStaging-1.7.55
+reactos/dll/directx/wine/d3d9           # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/d3drm          # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/d3dxof         # Synced to WineStaging-1.7.47
-reactos/dll/directx/wine/ddraw          # Synced to WineStaging-1.7.47
+reactos/dll/directx/wine/ddraw          # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/devenum        # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/dinput         # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/dinput8        # Synced to WineStaging-1.7.47
@@ -40,7 +40,7 @@ reactos/dll/directx/wine/dxdiagn        # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/msdmo          # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/qedit          # Synced to WineStaging-1.7.37
 reactos/dll/directx/wine/quartz         # Synced to WineStaging-1.7.47
-reactos/dll/directx/wine/wined3d        # Synced to WineStaging-1.7.47
+reactos/dll/directx/wine/wined3d        # Synced to WineStaging-1.7.55
 
 reactos/dll/win32/activeds            # Synced to WineStaging-1.7.47
 reactos/dll/win32/actxprxy            # Synced to WineStaging-1.7.47