https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7af3969e9fe68b5f55a08…
commit 7af3969e9fe68b5f55a088f93a6b69570822c733
Author:     Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sun May 27 03:52:04 2018 +0100
Commit:     Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Sun May 27 03:52:04 2018 +0100
    [D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 3.9. CORE-14656
---
 dll/directx/wine/d3d8/d3d8_private.h             |    3 +-
 dll/directx/wine/d3d8/device.c                   |  201 +-
 dll/directx/wine/d3d8/directx.c                  |    2 +-
 dll/directx/wine/d3d8/swapchain.c                |    9 +-
 dll/directx/wine/d3d9/d3d9_private.h             |    6 +-
 dll/directx/wine/d3d9/device.c                   |  189 +-
 dll/directx/wine/d3d9/directx.c                  |    8 +-
 dll/directx/wine/d3d9/swapchain.c                |   34 +-
 dll/directx/wine/d3d9/texture.c                  |   17 +-
 dll/directx/wine/ddraw/ddraw.c                   |   49 +-
 dll/directx/wine/ddraw/ddraw_private.h           |    7 +-
 dll/directx/wine/ddraw/device.c                  |   56 +-
 dll/directx/wine/ddraw/executebuffer.c           |   23 +-
 dll/directx/wine/ddraw/palette.c                 |    2 +-
 dll/directx/wine/ddraw/surface.c                 |   71 +-
 dll/directx/wine/ddraw/utils.c                   |    4 +-
 dll/directx/wine/ddraw/viewport.c                |  257 +--
 dll/directx/wine/wined3d/arb_program_shader.c    |  359 ++--
 dll/directx/wine/wined3d/ati_fragment_shader.c   |   37 +-
 dll/directx/wine/wined3d/buffer.c                |   10 +-
 dll/directx/wine/wined3d/context.c               | 1402 ++++++++++----
 dll/directx/wine/wined3d/cs.c                    |  180 +-
 dll/directx/wine/wined3d/device.c                |  373 ++--
 dll/directx/wine/wined3d/directx.c               |   88 +-
 dll/directx/wine/wined3d/glsl_shader.c           | 1159 +++++++++++-
 dll/directx/wine/wined3d/nvidia_texture_shader.c |    3 +
 dll/directx/wine/wined3d/resource.c              |   25 +-
 dll/directx/wine/wined3d/shader.c                |  230 ++-
 dll/directx/wine/wined3d/shader_sm4.c            |   79 +-
 dll/directx/wine/wined3d/state.c                 |  888 ++-------
 dll/directx/wine/wined3d/stateblock.c            |   34 +-
 dll/directx/wine/wined3d/surface.c               | 1252 ++++---------
 dll/directx/wine/wined3d/swapchain.c             |  111 +-
 dll/directx/wine/wined3d/texture.c               | 2188 ++++++++++------------
 dll/directx/wine/wined3d/utils.c                 |  149 +-
 dll/directx/wine/wined3d/view.c                  |   18 +-
 dll/directx/wine/wined3d/wined3d.spec            |   16 +-
 dll/directx/wine/wined3d/wined3d_gl.h            |    3 +-
 dll/directx/wine/wined3d/wined3d_main.c          |   15 +-
 dll/directx/wine/wined3d/wined3d_private.h       |  313 ++--
 media/doc/README.WINE                            |    8 +-
 sdk/include/reactos/wine/wined3d.h               |   74 +-
 42 files changed, 5257 insertions(+), 4695 deletions(-)
diff --git a/dll/directx/wine/d3d8/d3d8_private.h b/dll/directx/wine/d3d8/d3d8_private.h
index cba5dd647b..3fbc096b25 100644
--- a/dll/directx/wine/d3d8/d3d8_private.h
+++ b/dll/directx/wine/d3d8/d3d8_private.h
@@ -166,10 +166,11 @@ struct d3d8_swapchain
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
     IDirect3DDevice8 *parent_device;
+    unsigned int swap_interval;
 };
 HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc
*desc,
-        struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN;
+        unsigned int swap_interval, struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN;
 struct d3d8_surface
 {
diff --git a/dll/directx/wine/d3d8/device.c b/dll/directx/wine/d3d8/device.c
index 5daf6f46c2..616886bcaf 100644
--- a/dll/directx/wine/d3d8/device.c
+++ b/dll/directx/wine/d3d8/device.c
@@ -209,7 +209,7 @@ static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum
wined3d_swap_effe
 }
 static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS
*present_parameters,
-        const struct wined3d_swapchain_desc *swapchain_desc)
+        const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval)
 {
     present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
     present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
@@ -224,7 +224,7 @@ static void
present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS
             = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
     present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK;
     present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
-    present_parameters->FullScreen_PresentationInterval =
swapchain_desc->swap_interval;
+    present_parameters->FullScreen_PresentationInterval = presentation_interval;
 }
 static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT
effect)
@@ -245,6 +245,27 @@ static enum wined3d_swap_effect
wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFE
     }
 }
+static enum wined3d_swap_interval wined3dswapinterval_from_d3d(DWORD interval)
+{
+    switch (interval)
+    {
+        case D3DPRESENT_INTERVAL_IMMEDIATE:
+            return WINED3D_SWAP_INTERVAL_IMMEDIATE;
+        case D3DPRESENT_INTERVAL_ONE:
+            return WINED3D_SWAP_INTERVAL_ONE;
+        case D3DPRESENT_INTERVAL_TWO:
+            return WINED3D_SWAP_INTERVAL_TWO;
+        case D3DPRESENT_INTERVAL_THREE:
+            return WINED3D_SWAP_INTERVAL_THREE;
+        case D3DPRESENT_INTERVAL_FOUR:
+            return WINED3D_SWAP_INTERVAL_FOUR;
+        default:
+            FIXME("Unhandled presentation interval %#x.\n", interval);
+        case D3DPRESENT_INTERVAL_DEFAULT:
+            return WINED3D_SWAP_INTERVAL_DEFAULT;
+    }
+}
+
 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc
*swapchain_desc,
         const D3DPRESENT_PARAMETERS *present_parameters)
 {
@@ -261,6 +282,20 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct
wined3d_swapch
         WARN("Invalid backbuffer count %u.\n",
present_parameters->BackBufferCount);
         return FALSE;
     }
+    switch (present_parameters->FullScreen_PresentationInterval)
+    {
+        case D3DPRESENT_INTERVAL_DEFAULT:
+        case D3DPRESENT_INTERVAL_ONE:
+        case D3DPRESENT_INTERVAL_TWO:
+        case D3DPRESENT_INTERVAL_THREE:
+        case D3DPRESENT_INTERVAL_FOUR:
+        case D3DPRESENT_INTERVAL_IMMEDIATE:
+            break;
+        default:
+            WARN("Invalid presentation interval %#x.\n",
+                    present_parameters->FullScreen_PresentationInterval);
+            return FALSE;
+    }
     swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
     swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
@@ -278,7 +313,6 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct
wined3d_swapch
     swapchain_desc->flags
             = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) |
WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
     swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
-    swapchain_desc->swap_interval =
present_parameters->FullScreen_PresentationInterval;
     swapchain_desc->auto_restore_display_mode = TRUE;
     if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK)
@@ -294,7 +328,7 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS
*wined3d_caps)
     caps->Caps                      = wined3d_caps->Caps;
     caps->Caps2                     = wined3d_caps->Caps2;
     caps->Caps3                     = wined3d_caps->Caps3;
-    caps->PresentationIntervals     = wined3d_caps->PresentationIntervals;
+    caps->PresentationIntervals     = D3DPRESENT_INTERVAL_IMMEDIATE |
D3DPRESENT_INTERVAL_ONE;
     caps->CursorCaps                = wined3d_caps->CursorCaps;
     caps->DevCaps                   = wined3d_caps->DevCaps;
     caps->PrimitiveMiscCaps         = wined3d_caps->PrimitiveMiscCaps;
@@ -343,6 +377,57 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS
*wined3d_caps)
     caps->PixelShaderVersion        = wined3d_caps->PixelShaderVersion;
     caps->MaxPixelShaderValue       = wined3d_caps->PixelShader1xMaxValue;
+    caps->Caps2 &= D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_CANRENDERWINDOWED
+            | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES |
D3DCAPS2_FULLSCREENGAMMA
+            | D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_RESERVED;
+    caps->Caps3 &= D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_RESERVED;
+    caps->PrimitiveMiscCaps &= D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
+            | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
+            | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
+            | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
+            | D3DPMISCCAPS_NULLREFERENCE;
+    caps->RasterCaps &= D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT |
D3DPRASTERCAPS_ZTEST
+            | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE |
D3DPRASTERCAPS_ANTIALIASEDGES
+            | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS |
D3DPRASTERCAPS_ZBUFFERLESSHSR
+            | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY |
D3DPRASTERCAPS_WBUFFER
+            | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
+            | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE;
+    caps->SrcBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE |
D3DPBLENDCAPS_SRCCOLOR
+            | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA |
D3DPBLENDCAPS_INVSRCALPHA
+            | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA |
D3DPBLENDCAPS_DESTCOLOR
+            | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT |
D3DPBLENDCAPS_BOTHSRCALPHA
+            | D3DPBLENDCAPS_BOTHINVSRCALPHA;
+    caps->DestBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE |
D3DPBLENDCAPS_SRCCOLOR
+            | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA |
D3DPBLENDCAPS_INVSRCALPHA
+            | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA |
D3DPBLENDCAPS_DESTCOLOR
+            | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT |
D3DPBLENDCAPS_BOTHSRCALPHA
+            | D3DPBLENDCAPS_BOTHINVSRCALPHA;
+    caps->TextureCaps &= D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 |
D3DPTEXTURECAPS_ALPHA
+            | D3DPTEXTURECAPS_SQUAREONLY | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE
+            | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_NONPOW2CONDITIONAL
+            | D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP |
D3DPTEXTURECAPS_VOLUMEMAP
+            | D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_MIPVOLUMEMAP |
D3DPTEXTURECAPS_MIPCUBEMAP
+            | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2;
+    caps->TextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT |
D3DPTFILTERCAPS_MINFLINEAR
+            | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
+            | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
D3DPTFILTERCAPS_MAGFLINEAR
+            | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
+            | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC;
+    caps->CubeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT |
D3DPTFILTERCAPS_MINFLINEAR
+            | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
+            | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
D3DPTFILTERCAPS_MAGFLINEAR
+            | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
+            | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC;
+    caps->VolumeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT |
D3DPTFILTERCAPS_MINFLINEAR
+            | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
+            | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
D3DPTFILTERCAPS_MAGFLINEAR
+            | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
+            | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC;
+    caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
+    caps->VertexProcessingCaps &= D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
+            | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS |
D3DVTXPCAPS_LOCALVIEWER
+            | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_NO_VSDT_UBYTE4;
+
     /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */
     if (caps->PixelShaderVersion)
         caps->PixelShaderVersion = D3DPS_VERSION(1, 4);
@@ -353,8 +438,6 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS
*wined3d_caps)
     else
         caps->VertexShaderVersion = D3DVS_VERSION(0, 0);
     caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF,
caps->MaxVertexShaderConst);
-
-    caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
 }
 /* Handle table functions */
@@ -698,7 +781,8 @@ static HRESULT WINAPI
d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
     struct wined3d_swapchain_desc desc;
     struct d3d8_swapchain *object;
-    UINT i, count;
+    unsigned int swap_interval;
+    unsigned int i, count;
     HRESULT hr;
     TRACE("iface %p, present_parameters %p, swapchain %p.\n",
@@ -730,9 +814,11 @@ static HRESULT WINAPI
d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if
     if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters))
         return D3DERR_INVALIDCALL;
-    if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, &object)))
+    swap_interval =
wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval);
+    if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, swap_interval,
&object)))
         *swapchain = &object->IDirect3DSwapChain8_iface;
-    present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
+    present_parameters_from_wined3d_swapchain_desc(present_parameters,
+            &desc, present_parameters->FullScreen_PresentationInterval);
     return hr;
 }
@@ -806,6 +892,8 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
             NULL, reset_enum_callback, TRUE)))
     {
         present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
+        device->implicit_swapchain->swap_interval
+                =
wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval);
         wined3d_device_set_render_state(device->wined3d_device,
WINED3D_RS_POINTSIZE_MIN, 0);
         wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE,
                 !!swapchain_desc.enable_auto_depth_stencil);
@@ -1531,10 +1619,30 @@ static HRESULT WINAPI
d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface,
 static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8
*viewport)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_sub_resource_desc rt_desc;
+    struct wined3d_rendertarget_view *rtv;
+    struct d3d8_surface *surface;
     struct wined3d_viewport vp;
     TRACE("iface %p, viewport %p.\n", iface, viewport);
+    wined3d_mutex_lock();
+    if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_NOTFOUND;
+    }
+    surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
+    wined3d_texture_get_sub_resource_desc(surface->wined3d_texture,
surface->sub_resource_idx, &rt_desc);
+
+    if (viewport->X > rt_desc.width || viewport->Width > rt_desc.width -
viewport->X
+            || viewport->Y > rt_desc.height || viewport->Height >
rt_desc.height - viewport->Y)
+    {
+        WARN("Invalid viewport, returning D3DERR_INVALIDCALL.\n");
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
     vp.x = viewport->X;
     vp.y = viewport->Y;
     vp.width = viewport->Width;
@@ -1542,8 +1650,7 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8
*iface, const D3D
     vp.min_z = viewport->MinZ;
     vp.max_z = viewport->MaxZ;
-    wined3d_mutex_lock();
-    wined3d_device_set_viewport(device->wined3d_device, &vp);
+    wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
     wined3d_mutex_unlock();
     return D3D_OK;
@@ -1557,7 +1664,7 @@ static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8
*iface, D3DVIEWPO
     TRACE("iface %p, viewport %p.\n", iface, viewport);
     wined3d_mutex_lock();
-    wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport);
+    wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
     wined3d_mutex_unlock();
     viewport->X = wined3d_viewport.x;
@@ -2080,9 +2187,11 @@ static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8
*iface, DWORD
 static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface,
         DWORD info_id, void *info, DWORD info_size)
 {
-    FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface,
info_id, info, info_size);
+    TRACE("iface %p, info_id %#x, info %p, info_size %u.\n", iface, info_id,
info, info_size);
-    return D3D_OK;
+    if (info_id < 4)
+        return E_FAIL;
+    return S_FALSE;
 }
 static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface,
@@ -3162,40 +3271,40 @@ static void CDECL device_parent_activate(struct
wined3d_device_parent *device_pa
         InterlockedCompareExchange(&device->device_state,
D3D8_DEVICE_STATE_NOT_RESET, D3D8_DEVICE_STATE_LOST);
 }
-static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
*device_parent,
-        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+static HRESULT CDECL device_parent_texture_sub_resource_created(struct
wined3d_device_parent *device_parent,
+        enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture,
unsigned int sub_resource_idx,
         void **parent, const struct wined3d_parent_ops **parent_ops)
 {
-    struct d3d8_surface *d3d_surface;
+    TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u,
parent %p, parent_ops %p.\n",
+            device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops);
-    TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p,
parent_ops %p.\n",
-            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
-
-    if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface))))
-        return E_OUTOFMEMORY;
-
-    surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
-    *parent = d3d_surface;
-    TRACE("Created surface %p.\n", d3d_surface);
-
-    return D3D_OK;
-}
+    if (type == WINED3D_RTYPE_TEXTURE_2D)
+    {
+        struct d3d8_surface *d3d_surface;
-static HRESULT CDECL device_parent_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)
-{
-    struct d3d8_volume *d3d_volume;
+        if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface))))
+            return E_OUTOFMEMORY;
-    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);
+        surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
+        *parent = d3d_surface;
+        TRACE("Created surface %p.\n", d3d_surface);
+    }
+    else if (type == WINED3D_RTYPE_TEXTURE_3D)
+    {
+        struct d3d8_volume *d3d_volume;
-    if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume))))
-        return E_OUTOFMEMORY;
+        if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume))))
+            return E_OUTOFMEMORY;
-    volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
-    *parent = d3d_volume;
-    TRACE("Created volume %p.\n", d3d_volume);
+        volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
+        *parent = d3d_volume;
+        TRACE("Created volume %p.\n", d3d_volume);
+    }
+    else
+    {
+        ERR("Unhandled resource type %#x.\n", type);
+        return E_FAIL;
+    }
     return D3D_OK;
 }
@@ -3234,7 +3343,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct
wined3d_device_parent
     TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc,
swapchain);
-    if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain)))
+    if (FAILED(hr = d3d8_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT,
&d3d_swapchain)))
     {
         WARN("Failed to create swapchain, hr %#x.\n", hr);
         *swapchain = NULL;
@@ -3253,8 +3362,7 @@ static const struct wined3d_device_parent_ops
d3d8_wined3d_device_parent_ops =
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
     device_parent_activate,
-    device_parent_surface_created,
-    device_parent_volume_created,
+    device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
@@ -3356,7 +3464,8 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent,
struct wine
     wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN,
0);
     wined3d_mutex_unlock();
-    present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc);
+    present_parameters_from_wined3d_swapchain_desc(parameters,
+            &swapchain_desc, parameters->FullScreen_PresentationInterval);
     device->declArraySize = 16;
     if (!(device->decls = heap_alloc(device->declArraySize *
sizeof(*device->decls))))
@@ -3368,6 +3477,8 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent,
struct wine
     wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
     device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
+    device->implicit_swapchain->swap_interval
+            =
wined3dswapinterval_from_d3d(parameters->FullScreen_PresentationInterval);
     device->d3d_parent = &parent->IDirect3D8_iface;
     IDirect3D8_AddRef(device->d3d_parent);
diff --git a/dll/directx/wine/d3d8/directx.c b/dll/directx/wine/d3d8/directx.c
index 6e8f93a25c..68300c0a65 100644
--- a/dll/directx/wine/d3d8/directx.c
+++ b/dll/directx/wine/d3d8/directx.c
@@ -417,7 +417,7 @@ BOOL d3d8_init(struct d3d8 *d3d8)
     DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING
             | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER
             | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART
-            | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT;
+            | WINED3D_LEGACY_CUBEMAP_FILTERING;
     d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
     d3d8->refcount = 1;
diff --git a/dll/directx/wine/d3d8/swapchain.c b/dll/directx/wine/d3d8/swapchain.c
index 3a588b5e8c..39e3b23873 100644
--- a/dll/directx/wine/d3d8/swapchain.c
+++ b/dll/directx/wine/d3d8/swapchain.c
@@ -105,7 +105,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d8_swapchain_Present(IDirect3DSwapChai
     wined3d_mutex_lock();
     hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
-            src_rect, dst_rect, dst_window_override, 0, 0);
+            src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0);
     wined3d_mutex_unlock();
     return hr;
@@ -167,12 +167,13 @@ static const struct wined3d_parent_ops
d3d8_swapchain_wined3d_parent_ops =
 };
 static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_device
*device,
-        struct wined3d_swapchain_desc *desc)
+        struct wined3d_swapchain_desc *desc, unsigned int swap_interval)
 {
     HRESULT hr;
     swapchain->refcount = 1;
     swapchain->IDirect3DSwapChain8_iface.lpVtbl = &d3d8_swapchain_vtbl;
+    swapchain->swap_interval = swap_interval;
     wined3d_mutex_lock();
     hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
@@ -192,7 +193,7 @@ static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct
d3d8_devi
 }
 HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc
*desc,
-        struct d3d8_swapchain **swapchain)
+        unsigned int swap_interval, struct d3d8_swapchain **swapchain)
 {
     struct d3d8_swapchain *object;
     HRESULT hr;
@@ -200,7 +201,7 @@ HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct
wined3d_swapcha
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
-    if (FAILED(hr = swapchain_init(object, device, desc)))
+    if (FAILED(hr = swapchain_init(object, device, desc, swap_interval)))
     {
         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
         heap_free(object);
diff --git a/dll/directx/wine/d3d9/d3d9_private.h b/dll/directx/wine/d3d9/d3d9_private.h
index ba19e5fb08..c50aabf593 100644
--- a/dll/directx/wine/d3d9/d3d9_private.h
+++ b/dll/directx/wine/d3d9/d3d9_private.h
@@ -57,7 +57,7 @@ BOOL is_gdi_compat_wined3dformat(enum wined3d_format_id format)
DECLSPEC_HIDDEN;
 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN;
 unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags) DECLSPEC_HIDDEN;
 void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS
*present_parameters,
-        const struct wined3d_swapchain_desc *swapchain_desc) DECLSPEC_HIDDEN;
+        const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval)
DECLSPEC_HIDDEN;
 void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps)
DECLSPEC_HIDDEN;
 struct d3d9
@@ -101,7 +101,6 @@ struct d3d9_device
     UINT index_buffer_size;
     UINT index_buffer_pos;
-    struct d3d9_texture *textures[D3D9_MAX_TEXTURE_UNITS];
     struct d3d9_surface *render_targets[D3D_MAX_SIMULTANEOUS_RENDERTARGETS];
     LONG device_state;
@@ -151,10 +150,11 @@ struct d3d9_swapchain
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
     IDirect3DDevice9Ex *parent_device;
+    unsigned int swap_interval;
 };
 HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc
*desc,
-        struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN;
+        unsigned int swap_interval, struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN;
 struct d3d9_surface
 {
diff --git a/dll/directx/wine/d3d9/device.c b/dll/directx/wine/d3d9/device.c
index bc73699e52..2f3ad2880d 100644
--- a/dll/directx/wine/d3d9/device.c
+++ b/dll/directx/wine/d3d9/device.c
@@ -231,7 +231,7 @@ static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum
wined3d_swap_effe
 }
 void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS
*present_parameters,
-        const struct wined3d_swapchain_desc *swapchain_desc)
+        const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval)
 {
     present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
     present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
@@ -247,7 +247,7 @@ void
present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *prese
             = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
     present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK;
     present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
-    present_parameters->PresentationInterval = swapchain_desc->swap_interval;
+    present_parameters->PresentationInterval = presentation_interval;
 }
 static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT
effect)
@@ -270,6 +270,27 @@ static enum wined3d_swap_effect
wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFE
     }
 }
+static enum wined3d_swap_interval wined3dswapinterval_from_d3d(DWORD interval)
+{
+    switch (interval)
+    {
+        case D3DPRESENT_INTERVAL_IMMEDIATE:
+            return WINED3D_SWAP_INTERVAL_IMMEDIATE;
+        case D3DPRESENT_INTERVAL_ONE:
+            return WINED3D_SWAP_INTERVAL_ONE;
+        case D3DPRESENT_INTERVAL_TWO:
+            return WINED3D_SWAP_INTERVAL_TWO;
+        case D3DPRESENT_INTERVAL_THREE:
+            return WINED3D_SWAP_INTERVAL_THREE;
+        case D3DPRESENT_INTERVAL_FOUR:
+            return WINED3D_SWAP_INTERVAL_FOUR;
+        default:
+            FIXME("Unhandled presentation interval %#x.\n", interval);
+        case D3DPRESENT_INTERVAL_DEFAULT:
+            return WINED3D_SWAP_INTERVAL_DEFAULT;
+    }
+}
+
 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc
*swapchain_desc,
         const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended)
 {
@@ -288,6 +309,19 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct
wined3d_swapch
         WARN("Invalid backbuffer count %u.\n",
present_parameters->BackBufferCount);
         return FALSE;
     }
+    switch (present_parameters->PresentationInterval)
+    {
+        case D3DPRESENT_INTERVAL_DEFAULT:
+        case D3DPRESENT_INTERVAL_ONE:
+        case D3DPRESENT_INTERVAL_TWO:
+        case D3DPRESENT_INTERVAL_THREE:
+        case D3DPRESENT_INTERVAL_FOUR:
+        case D3DPRESENT_INTERVAL_IMMEDIATE:
+            break;
+        default:
+            WARN("Invalid presentation interval %#x.\n",
present_parameters->PresentationInterval);
+            return FALSE;
+    }
     swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
     swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
@@ -305,7 +339,6 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct
wined3d_swapch
     swapchain_desc->flags
             = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) |
WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
     swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
-    swapchain_desc->swap_interval = present_parameters->PresentationInterval;
     swapchain_desc->auto_restore_display_mode = TRUE;
     if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK)
@@ -330,7 +363,7 @@ void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS
*wined3d_caps)
     caps->Caps                              = wined3d_caps->Caps;
     caps->Caps2                             = wined3d_caps->Caps2;
     caps->Caps3                             = wined3d_caps->Caps3;
-    caps->PresentationIntervals             = wined3d_caps->PresentationIntervals;
+    caps->PresentationIntervals             = D3DPRESENT_INTERVAL_IMMEDIATE |
D3DPRESENT_INTERVAL_ONE;
     caps->CursorCaps                        = wined3d_caps->CursorCaps;
     caps->DevCaps                           = wined3d_caps->DevCaps;
     caps->PrimitiveMiscCaps                 = wined3d_caps->PrimitiveMiscCaps;
@@ -743,7 +776,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d9_device_CreateAdditionalSwapChain(ID
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct wined3d_swapchain_desc desc;
     struct d3d9_swapchain *object;
-    UINT i, count;
+    unsigned int swap_interval;
+    unsigned int i, count;
     HRESULT hr;
     TRACE("iface %p, present_parameters %p, swapchain %p.\n",
@@ -776,9 +810,11 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d9_device_CreateAdditionalSwapChain(ID
     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)))
+    swap_interval =
wined3dswapinterval_from_d3d(present_parameters->PresentationInterval);
+    if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, swap_interval,
&object)))
         *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
-    present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
+    present_parameters_from_wined3d_swapchain_desc(present_parameters,
+            &desc, present_parameters->PresentationInterval);
     return hr;
 }
@@ -934,6 +970,8 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
         }
         else
         {
+            device->implicit_swapchains[0]->swap_interval
+                    =
wined3dswapinterval_from_d3d(present_parameters->PresentationInterval);
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;
@@ -943,10 +981,6 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
             device->device_state = D3D9_DEVICE_STATE_OK;
         }
-        if (!device->d3d_parent->extended)
-            for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
-                device->textures[i] = NULL;
-
         rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0);
         device->render_targets[0] =
wined3d_rendertarget_view_get_sub_resource_parent(rtv);
         for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i)
@@ -976,7 +1010,8 @@ 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;
+    struct d3d9_swapchain *swapchain;
+    unsigned int i;
     HRESULT hr;
     TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region
%p.\n",
@@ -991,8 +1026,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d9_device_Present(IDirect3DDevice9Ex *
     wined3d_mutex_lock();
     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, 0, 0)))
+        swapchain = device->implicit_swapchains[i];
+        if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
+                src_rect, dst_rect, dst_window_override, swapchain->swap_interval,
0)))
         {
             wined3d_mutex_unlock();
             return hr;
@@ -1500,7 +1536,7 @@ static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex
*iface,
     hr = wined3d_device_copy_sub_resource_region(device->wined3d_device,
             wined3d_texture_get_resource(dst->wined3d_texture),
dst->sub_resource_idx, dst_point ? dst_point->x : 0,
             dst_point ? dst_point->y : 0, 0,
wined3d_texture_get_resource(src->wined3d_texture),
-            src->sub_resource_idx, &src_box);
+            src->sub_resource_idx, &src_box, 0);
     if (SUCCEEDED(hr) && dst->texture)
         d3d9_texture_flag_auto_gen_mipmap(dst->texture);
@@ -2032,7 +2068,7 @@ static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex
*iface, const D
     vp.max_z = viewport->MaxZ;
     wined3d_mutex_lock();
-    wined3d_device_set_viewport(device->wined3d_device, &vp);
+    wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
     wined3d_mutex_unlock();
     return D3D_OK;
@@ -2046,7 +2082,7 @@ static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex
*iface, D3DVIEW
     TRACE("iface %p, viewport %p.\n", iface, viewport);
     wined3d_mutex_lock();
-    wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport);
+    wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
     wined3d_mutex_unlock();
     viewport->X = wined3d_viewport.x;
@@ -2362,13 +2398,6 @@ static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex
*iface, DWORD st
     wined3d_mutex_lock();
     hr = wined3d_device_set_texture(device->wined3d_device, stage,
             texture_impl ? texture_impl->wined3d_texture : NULL);
-    if (SUCCEEDED(hr))
-    {
-        unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage -
D3DVERTEXTEXTURESAMPLER0 + 16 : stage;
-
-        if (stage < ARRAY_SIZE(device->textures))
-            device->textures[i] = texture_impl;
-    }
     wined3d_mutex_unlock();
     return hr;
@@ -2535,7 +2564,7 @@ static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex
*iface, cons
     TRACE("iface %p, rect %p.\n", iface, rect);
     wined3d_mutex_lock();
-    wined3d_device_set_scissor_rect(device->wined3d_device, rect);
+    wined3d_device_set_scissor_rects(device->wined3d_device, 1, rect);
     wined3d_mutex_unlock();
     return D3D_OK;
@@ -2548,7 +2577,7 @@ static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex
*iface, RECT
     TRACE("iface %p, rect %p.\n", iface, rect);
     wined3d_mutex_lock();
-    wined3d_device_get_scissor_rect(device->wined3d_device, rect);
+    wined3d_device_get_scissor_rects(device->wined3d_device, NULL, rect);
     wined3d_mutex_unlock();
     return D3D_OK;
@@ -2612,11 +2641,15 @@ static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex
*iface)
 /* wined3d critical section must be taken by the caller. */
 static void d3d9_generate_auto_mipmaps(struct d3d9_device *device)
 {
-    unsigned int i;
+    struct wined3d_texture *texture;
+    unsigned int i, stage;
-    for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
-        if (device->textures[i])
-            d3d9_texture_gen_auto_mipmap(device->textures[i]);
+    for (i = 0; i < D3D9_MAX_TEXTURE_UNITS; ++i)
+    {
+        stage = i >= 16 ? i - 16 + D3DVERTEXTEXTURESAMPLER0 : i;
+        if ((texture = wined3d_device_get_texture(device->wined3d_device, stage)))
+            d3d9_texture_gen_auto_mipmap(wined3d_texture_get_parent(texture));
+    }
 }
 static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
@@ -3667,7 +3700,8 @@ 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;
+    struct d3d9_swapchain *swapchain;
+    unsigned int i;
     HRESULT hr;
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region
%p, flags %#x.\n",
@@ -3683,8 +3717,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d9_device_PresentEx(IDirect3DDevice9Ex
     wined3d_mutex_lock();
     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, 0, flags)))
+        swapchain = device->implicit_swapchains[i];
+        if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
+                src_rect, dst_rect, dst_window_override, swapchain->swap_interval,
flags)))
         {
             wined3d_mutex_unlock();
             return hr;
@@ -3727,21 +3762,31 @@ static HRESULT WINAPI
d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *ifa
 static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT
max_latency)
 {
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
     TRACE("iface %p, max_latency %u.\n", iface, max_latency);
-    if (max_latency)
-        FIXME("Ignoring max_latency %u.\n", max_latency);
+    if (max_latency > 30)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    wined3d_device_set_max_frame_latency(device->wined3d_device, max_latency);
+    wined3d_mutex_unlock();
     return S_OK;
 }
 static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT
*max_latency)
 {
-    FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    *max_latency = 2;
+    TRACE("iface %p, max_latency %p.\n", iface, max_latency);
-    return E_NOTIMPL;
+    wined3d_mutex_lock();
+    *max_latency = wined3d_device_get_max_frame_latency(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return S_OK;
 }
 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND
dst_window)
@@ -4050,40 +4095,40 @@ static void CDECL device_parent_activate(struct
wined3d_device_parent *device_pa
         InterlockedCompareExchange(&device->device_state,
D3D9_DEVICE_STATE_NOT_RESET, D3D9_DEVICE_STATE_LOST);
 }
-static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
*device_parent,
-        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+static HRESULT CDECL device_parent_texture_sub_resource_created(struct
wined3d_device_parent *device_parent,
+        enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture,
unsigned int sub_resource_idx,
         void **parent, const struct wined3d_parent_ops **parent_ops)
 {
-    struct d3d9_surface *d3d_surface;
+    TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u,
parent %p, parent_ops %p.\n",
+            device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops);
-    TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p,
parent_ops %p.\n",
-            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
-
-    if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface))))
-        return E_OUTOFMEMORY;
+    if (type == WINED3D_RTYPE_TEXTURE_2D)
+    {
+        struct d3d9_surface *d3d_surface;
-    surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
-    *parent = d3d_surface;
-    TRACE("Created surface %p.\n", d3d_surface);
+        if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface))))
+            return E_OUTOFMEMORY;
-    return D3D_OK;
-}
-
-static HRESULT CDECL device_parent_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)
-{
-    struct d3d9_volume *d3d_volume;
+        surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
+        *parent = d3d_surface;
+        TRACE("Created surface %p.\n", d3d_surface);
+    }
+    else if (type == WINED3D_RTYPE_TEXTURE_3D)
+    {
+        struct d3d9_volume *d3d_volume;
-    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 = heap_alloc_zero(sizeof(*d3d_volume))))
+            return E_OUTOFMEMORY;
-    if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume))))
-        return E_OUTOFMEMORY;
-
-    volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
-    *parent = d3d_volume;
-    TRACE("Created volume %p.\n", d3d_volume);
+        volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
+        *parent = d3d_volume;
+        TRACE("Created volume %p.\n", d3d_volume);
+    }
+    else
+    {
+        ERR("Unhandled resource type %#x.\n", type);
+        return E_FAIL;
+    }
     return D3D_OK;
 }
@@ -4128,8 +4173,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct
wined3d_device_parent
     TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc,
swapchain);
-    hr = d3d9_swapchain_create(device, desc, &d3d_swapchain);
-    if (FAILED(hr))
+    if (FAILED(hr = d3d9_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT,
&d3d_swapchain)))
     {
         WARN("Failed to create swapchain, hr %#x.\n", hr);
         *swapchain = NULL;
@@ -4148,8 +4192,7 @@ static const struct wined3d_device_parent_ops
d3d9_wined3d_device_parent_ops =
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
     device_parent_activate,
-    device_parent_surface_created,
-    device_parent_volume_created,
+    device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
@@ -4272,10 +4315,16 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9
*parent, struct wine
         wined3d_mutex_unlock();
         return E_OUTOFMEMORY;
     }
+    for (i = 0; i < device->implicit_swapchain_count; ++i)
+    {
+        device->implicit_swapchains[i]->swap_interval
+                = wined3dswapinterval_from_d3d(parameters[i].PresentationInterval);
+    }
     for (i = 0; i < count; ++i)
     {
-        present_parameters_from_wined3d_swapchain_desc(¶meters[i],
&swapchain_desc[i]);
+        present_parameters_from_wined3d_swapchain_desc(¶meters[i],
+                &swapchain_desc[i], parameters[i].PresentationInterval);
     }
     wined3d_mutex_unlock();
diff --git a/dll/directx/wine/d3d9/directx.c b/dll/directx/wine/d3d9/directx.c
index 644766c2e9..98f4a99c49 100644
--- a/dll/directx/wine/d3d9/directx.c
+++ b/dll/directx/wine/d3d9/directx.c
@@ -254,6 +254,12 @@ static HRESULT WINAPI d3d9_CheckDeviceFormat(IDirect3D9Ex *iface,
UINT adapter,
     TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x,
resource_type %#x, format %#x.\n",
             iface, adapter, device_type, adapter_format, usage, resource_type, format);
+    if (!adapter_format)
+    {
+        WARN("Invalid adapter format.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
     usage = usage & (WINED3DUSAGE_MASK | WINED3DUSAGE_QUERY_MASK);
     switch (resource_type)
     {
@@ -579,7 +585,7 @@ BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended)
     DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE |
WINED3D_PIXEL_CENTER_INTEGER
             | WINED3D_SRGB_READ_WRITE_CONTROL | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR
             | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING
-            | WINED3D_NORMALIZED_DEPTH_BIAS | WINED3D_LIMIT_VIEWPORT;
+            | WINED3D_NORMALIZED_DEPTH_BIAS;
     if (!extended)
         flags |= WINED3D_VIDMEM_ACCOUNTING;
diff --git a/dll/directx/wine/d3d9/swapchain.c b/dll/directx/wine/d3d9/swapchain.c
index dbb3f45b91..d303f3f956 100644
--- a/dll/directx/wine/d3d9/swapchain.c
+++ b/dll/directx/wine/d3d9/swapchain.c
@@ -25,6 +25,27 @@
 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+static DWORD d3dpresentationinterval_from_wined3dswapinterval(enum wined3d_swap_interval
interval)
+{
+    switch (interval)
+    {
+        case WINED3D_SWAP_INTERVAL_IMMEDIATE:
+            return D3DPRESENT_INTERVAL_IMMEDIATE;
+        case WINED3D_SWAP_INTERVAL_ONE:
+            return D3DPRESENT_INTERVAL_ONE;
+        case WINED3D_SWAP_INTERVAL_TWO:
+            return D3DPRESENT_INTERVAL_TWO;
+        case WINED3D_SWAP_INTERVAL_THREE:
+            return D3DPRESENT_INTERVAL_THREE;
+        case WINED3D_SWAP_INTERVAL_FOUR:
+            return D3DPRESENT_INTERVAL_FOUR;
+        default:
+            ERR("Invalid swap interval %#x.\n", interval);
+        case WINED3D_SWAP_INTERVAL_DEFAULT:
+            return D3DPRESENT_INTERVAL_DEFAULT;
+    }
+}
+
 static inline struct d3d9_swapchain
*impl_from_IDirect3DSwapChain9Ex(IDirect3DSwapChain9Ex *iface)
 {
     return CONTAINING_RECORD(iface, struct d3d9_swapchain, IDirect3DSwapChain9Ex_iface);
@@ -137,7 +158,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
d3d9_swapchain_Present(IDirect3DSwapChai
     wined3d_mutex_lock();
     hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
-            src_rect, dst_rect, dst_window_override, 0, flags);
+            src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags);
     wined3d_mutex_unlock();
     return hr;
@@ -251,13 +272,15 @@ static HRESULT WINAPI
d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9Ex
 {
     struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     struct wined3d_swapchain_desc desc;
+    DWORD presentation_interval;
     TRACE("iface %p, parameters %p.\n", iface, parameters);
     wined3d_mutex_lock();
     wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &desc);
+    presentation_interval =
d3dpresentationinterval_from_wined3dswapinterval(swapchain->swap_interval);
     wined3d_mutex_unlock();
-    present_parameters_from_wined3d_swapchain_desc(parameters, &desc);
+    present_parameters_from_wined3d_swapchain_desc(parameters, &desc,
presentation_interval);
     return D3D_OK;
 }
@@ -344,12 +367,13 @@ static const struct wined3d_parent_ops
d3d9_swapchain_wined3d_parent_ops =
 };
 static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_device
*device,
-        struct wined3d_swapchain_desc *desc)
+        struct wined3d_swapchain_desc *desc, unsigned int swap_interval)
 {
     HRESULT hr;
     swapchain->refcount = 1;
     swapchain->IDirect3DSwapChain9Ex_iface.lpVtbl = &d3d9_swapchain_vtbl;
+    swapchain->swap_interval = swap_interval;
     wined3d_mutex_lock();
     hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
@@ -369,7 +393,7 @@ static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct
d3d9_devi
 }
 HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc
*desc,
-        struct d3d9_swapchain **swapchain)
+        unsigned int swap_interval, struct d3d9_swapchain **swapchain)
 {
     struct d3d9_swapchain *object;
     HRESULT hr;
@@ -377,7 +401,7 @@ HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct
wined3d_swapcha
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
-    if (FAILED(hr = swapchain_init(object, device, desc)))
+    if (FAILED(hr = swapchain_init(object, device, desc, swap_interval)))
     {
         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
         heap_free(object);
diff --git a/dll/directx/wine/d3d9/texture.c b/dll/directx/wine/d3d9/texture.c
index c97fa6b021..7b74ac5b9e 100644
--- a/dll/directx/wine/d3d9/texture.c
+++ b/dll/directx/wine/d3d9/texture.c
@@ -1339,9 +1339,22 @@ HRESULT texture_init(struct d3d9_texture *texture, struct
d3d9_device *device,
             WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning
D3DERR_INVALIDCALL.\n", levels);
             return D3DERR_INVALIDCALL;
         }
-        flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS;
+        wined3d_mutex_lock();
+        hr = wined3d_check_device_format(device->d3d_parent->wined3d, 0,
WINED3D_DEVICE_TYPE_HAL, WINED3DFMT_B8G8R8A8_UNORM,
+                WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_GENMIPMAP,
WINED3D_RTYPE_TEXTURE_2D, wined3dformat_from_d3dformat(format));
+        wined3d_mutex_unlock();
+        if (hr == D3D_OK)
+        {
+            flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS;
+            levels = 0;
+        }
+        else
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP not supported on D3DFORMAT %#x, creating a
texture "
+                    "with a single level.\n", format);
+            levels = 1;
+        }
         texture->autogen_filter_type = D3DTEXF_LINEAR;
-        levels = 0;
     }
     else
     {
diff --git a/dll/directx/wine/ddraw/ddraw.c b/dll/directx/wine/ddraw/ddraw.c
index e5205c0d00..6b5ccece46 100644
--- a/dll/directx/wine/ddraw/ddraw.c
+++ b/dll/directx/wine/ddraw/ddraw.c
@@ -633,8 +633,9 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND
window, BOOL win
     swapchain_desc.backbuffer_width = mode.width;
     swapchain_desc.backbuffer_height = mode.height;
     swapchain_desc.backbuffer_format = mode.format_id;
-    swapchain_desc.backbuffer_usage = WINED3DUSAGE_RENDERTARGET;
-    swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
+    swapchain_desc.backbuffer_usage = 0;
+    swapchain_desc.backbuffer_count = 1;
+    swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
     swapchain_desc.device_window = window;
     swapchain_desc.windowed = windowed;
     swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
@@ -2099,7 +2100,7 @@ static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
     ddraw->flags |= DDRAW_GDI_FLIP;
     if (ddraw->primary)
-        ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE);
+        ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE, 0);
     return DD_OK;
 }
@@ -4909,18 +4910,19 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw)
     ddraw->device_state = DDRAW_DEVICE_STATE_OK;
 }
-static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
*device_parent,
-        struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+static HRESULT CDECL device_parent_texture_sub_resource_created(struct
wined3d_device_parent *device_parent,
+        enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture,
unsigned int sub_resource_idx,
         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, wined3d_texture %p, sub_resource_idx %u, parent %p,
parent_ops %p.\n",
-            device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
+    TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u,
parent %p, parent_ops %p.\n",
+            device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops);
     /* We have a swapchain or wined3d internal texture. */
-    if (!wined3d_texture_get_parent(wined3d_texture) ||
wined3d_texture_get_parent(wined3d_texture) == ddraw)
+    if (type != WINED3D_RTYPE_TEXTURE_2D || !wined3d_texture_get_parent(wined3d_texture)
+            || wined3d_texture_get_parent(wined3d_texture) == ddraw)
     {
         *parent = NULL;
         *parent_ops = &ddraw_null_wined3d_parent_ops;
@@ -4945,19 +4947,6 @@ static HRESULT CDECL device_parent_surface_created(struct
wined3d_device_parent
     return DD_OK;
 }
-static HRESULT CDECL device_parent_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)
-{
-    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;
-
-    return DD_OK;
-}
-
 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent)
 {
     struct ddraw *ddraw = parent;
@@ -4974,25 +4963,26 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct
wined3d_devic
         struct wined3d_texture **texture)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
+    const struct wined3d_parent_ops *parent_ops;
     HRESULT hr;
     TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x,
texture %p.\n",
             device_parent, container_parent, desc, texture_flags, texture);
-    if (ddraw->wined3d_frontbuffer)
-    {
-        ERR("Frontbuffer already created.\n");
-        return E_FAIL;
-    }
+    if (!ddraw->wined3d_frontbuffer)
+        parent_ops = &ddraw_frontbuffer_parent_ops;
+    else
+        parent_ops = &ddraw_null_wined3d_parent_ops;
     if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1,
-            texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw,
&ddraw_frontbuffer_parent_ops, texture)))
+            texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, parent_ops,
texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
-    ddraw->wined3d_frontbuffer = *texture;
+    if (!ddraw->wined3d_frontbuffer)
+        ddraw->wined3d_frontbuffer = *texture;
     return hr;
 }
@@ -5023,8 +5013,7 @@ static const struct wined3d_device_parent_ops
ddraw_wined3d_device_parent_ops =
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
     device_parent_activate,
-    device_parent_surface_created,
-    device_parent_volume_created,
+    device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
diff --git a/dll/directx/wine/ddraw/ddraw_private.h
b/dll/directx/wine/ddraw/ddraw_private.h
index 1454e8012a..9757008e92 100644
--- a/dll/directx/wine/ddraw/ddraw_private.h
+++ b/dll/directx/wine/ddraw/ddraw_private.h
@@ -59,14 +59,15 @@ struct FvfToDecl
 #define DDRAW_NO3D              0x00000008
 #define DDRAW_SCL_DDRAW1        0x00000010
 #define DDRAW_SCL_RECURSIVE     0x00000020
-#define DDRAW_GDI_FLIP          0x00000040
+#define DDRAW_SWAPPED           0x00000040
+#define DDRAW_GDI_FLIP          0x00000080
 #define DDRAW_STRIDE_ALIGNMENT  8
 #define DDRAW_WINED3D_FLAGS     (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \
         | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES |
WINED3D_PIXEL_CENTER_INTEGER \
         | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \
-        | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT)
+        | WINED3D_LEGACY_CUBEMAP_FILTERING)
 enum ddraw_device_state
 {
@@ -220,7 +221,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw
*ddraw,
         struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
         const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
-        const RECT *rect, BOOL read) DECLSPEC_HIDDEN;
+        const RECT *rect, BOOL read, unsigned int swap_interval) DECLSPEC_HIDDEN;
 static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface)
 {
diff --git a/dll/directx/wine/ddraw/device.c b/dll/directx/wine/ddraw/device.c
index 24dbd3be50..799b2bcaa0 100644
--- a/dll/directx/wine/ddraw/device.c
+++ b/dll/directx/wine/ddraw/device.c
@@ -5296,25 +5296,12 @@ static HRESULT WINAPI
d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWO
     return hr;
 }
-/*****************************************************************************
- * IDirect3DDevice7::SetViewport
- *
- * Sets the current viewport.
- *
- * Version 7 only, but IDirect3DViewport uses this call for older
- * versions
- *
- * Params:
- *  Data: The new viewport to set
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Data is NULL
- *
- *****************************************************************************/
 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
+    struct wined3d_sub_resource_desc rt_desc;
+    struct wined3d_rendertarget_view *rtv;
+    struct ddraw_surface *surface;
     struct wined3d_viewport vp;
     TRACE("iface %p, viewport %p.\n", iface, viewport);
@@ -5322,6 +5309,23 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface,
D3DVIEWPORT7 *vi
     if (!viewport)
         return DDERR_INVALIDPARAMS;
+    wined3d_mutex_lock();
+    if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
+    {
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+    surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
+    wined3d_texture_get_sub_resource_desc(surface->wined3d_texture,
surface->sub_resource_idx, &rt_desc);
+
+    if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width -
viewport->dwX
+            || viewport->dwY > rt_desc.height || viewport->dwHeight >
rt_desc.height - viewport->dwY)
+    {
+        WARN("Invalid viewport, returning E_INVALIDARG.\n");
+        wined3d_mutex_unlock();
+        return E_INVALIDARG;
+    }
+
     vp.x = viewport->dwX;
     vp.y = viewport->dwY;
     vp.width = viewport->dwWidth;
@@ -5329,8 +5333,7 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface,
D3DVIEWPORT7 *vi
     vp.min_z = viewport->dvMinZ;
     vp.max_z = viewport->dvMaxZ;
-    wined3d_mutex_lock();
-    wined3d_device_set_viewport(device->wined3d_device, &vp);
+    wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
     wined3d_mutex_unlock();
     return D3D_OK;
@@ -5353,21 +5356,6 @@ static HRESULT WINAPI
d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *ifac
     return hr;
 }
-/*****************************************************************************
- * IDirect3DDevice::GetViewport
- *
- * Returns the current viewport
- *
- * Version 7
- *
- * Params:
- *  Data: D3D7Viewport structure to write the viewport information to
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Data is NULL
- *
- *****************************************************************************/
 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
@@ -5379,7 +5367,7 @@ static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface,
D3DVIEWPORT7 *vi
         return DDERR_INVALIDPARAMS;
     wined3d_mutex_lock();
-    wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport);
+    wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
     wined3d_mutex_unlock();
     viewport->dwX = wined3d_viewport.x;
diff --git a/dll/directx/wine/ddraw/executebuffer.c
b/dll/directx/wine/ddraw/executebuffer.c
index 17bea2764c..e2c4fc11ab 100644
--- a/dll/directx/wine/ddraw/executebuffer.c
+++ b/dll/directx/wine/ddraw/executebuffer.c
@@ -348,7 +348,7 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
wined3d_device_copy_sub_resource_region(device->wined3d_device,
wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0,
                                     ci->wDest * sizeof(D3DTLVERTEX), 0, 0,
-
wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box);
+
wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box, 0);
                             break;
                         default:
@@ -610,9 +610,16 @@ static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
     struct wined3d_map_desc map_desc;
     struct wined3d_box box = {0};
     HRESULT hr;
+    DWORD buf_size = buffer->desc.dwBufferSize, copy_size;
     TRACE("iface %p, data %p.\n", iface, data);
+    if (data->dwSize != sizeof(*data))
+    {
+        WARN("data->dwSize is %u, returning DDERR_INVALIDPARAMS.\n",
data->dwSize);
+        return DDERR_INVALIDPARAMS;
+    }
+
     /* Skip past previous vertex data. */
     buffer->src_vertex_pos += buffer->data.dwVertexCount;
@@ -659,7 +666,7 @@ static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
         buffer->src_vertex_pos = 0;
     }
-    if (data->dwVertexCount)
+    if (data->dwVertexCount && (!buf_size || data->dwVertexOffset <
buf_size))
     {
         box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX);
         box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX);
@@ -667,8 +674,11 @@ static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
                 0, &map_desc, &box, WINED3D_MAP_WRITE)))
             return hr;
-        memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset,
-                data->dwVertexCount * sizeof(D3DVERTEX));
+        copy_size = data->dwVertexCount * sizeof(D3DVERTEX);
+        if (buf_size)
+            copy_size = min(copy_size, buf_size - data->dwVertexOffset);
+
+        memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset,
copy_size);
         wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer),
0);
     }
@@ -696,12 +706,11 @@ static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
 static HRESULT WINAPI d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer *iface,
D3DEXECUTEDATA *data)
 {
     struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
-    DWORD dwSize;
     TRACE("iface %p, data %p.\n", iface, data);
-    dwSize = data->dwSize;
-    memcpy(data, &buffer->data, dwSize);
+    /* Tests show that dwSize is ignored. */
+    memcpy(data, &buffer->data, sizeof(*data));
     if (TRACE_ON(ddraw))
     {
diff --git a/dll/directx/wine/ddraw/palette.c b/dll/directx/wine/ddraw/palette.c
index 5148832cab..87aec96443 100644
--- a/dll/directx/wine/ddraw/palette.c
+++ b/dll/directx/wine/ddraw/palette.c
@@ -176,7 +176,7 @@ static HRESULT WINAPI ddraw_palette_SetEntries(IDirectDrawPalette
*iface,
     hr = wined3d_palette_set_entries(palette->wined3d_palette, flags, start, count,
entries);
     if (SUCCEEDED(hr) && palette->flags & DDPCAPS_PRIMARYSURFACE)
-        ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE);
+        ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE, 0);
     wined3d_mutex_unlock();
diff --git a/dll/directx/wine/ddraw/surface.c b/dll/directx/wine/ddraw/surface.c
index 5eefc228e6..e188396eb3 100644
--- a/dll/directx/wine/ddraw/surface.c
+++ b/dll/directx/wine/ddraw/surface.c
@@ -40,15 +40,22 @@ static inline struct ddraw_surface
*impl_from_IDirectDrawGammaControl(IDirectDra
  * applications from drawing to the screen while we've locked the frontbuffer.
  * We'd like to do this in wined3d instead, but for that to work wined3d needs
  * to support windowless rendering first. */
-HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect,
BOOL read)
+HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
+        const RECT *rect, BOOL read, unsigned int swap_interval)
 {
-    struct ddraw *ddraw = surface->ddraw;
+    struct wined3d_texture *dst_texture;
     HDC surface_dc, screen_dc;
     int x, y, w, h;
     HRESULT hr;
     BOOL ret;
     RECT r;
+    if (surface->ddraw->flags & DDRAW_SWAPPED && !read)
+    {
+        surface->ddraw->flags &= ~DDRAW_SWAPPED;
+        rect = NULL;
+    }
+
     if (!rect)
     {
         SetRect(&r, 0, 0, surface->surface_desc.dwWidth,
surface->surface_desc.dwHeight);
@@ -63,15 +70,25 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface
*surface, const RE
     if (w <= 0 || h <= 0)
         return DD_OK;
-    if (ddraw->swapchain_window && !(ddraw->flags & DDRAW_GDI_FLIP))
+    if (surface->ddraw->swapchain_window && !(surface->ddraw->flags
& DDRAW_GDI_FLIP))
     {
         /* Nothing to do, we control the frontbuffer, or at least the parts we
          * care about. */
         if (read)
             return DD_OK;
-        return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect,
-                surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL,
WINED3D_TEXF_POINT);
+        if (swap_interval)
+            dst_texture =
wined3d_swapchain_get_back_buffer(surface->ddraw->wined3d_swapchain, 0);
+        else
+            dst_texture = surface->ddraw->wined3d_frontbuffer;
+
+        if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect,
surface->wined3d_texture,
+                surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT))
&& swap_interval)
+        {
+            hr = wined3d_swapchain_present(surface->ddraw->wined3d_swapchain, rect,
rect, NULL, swap_interval, 0);
+            surface->ddraw->flags |= DDRAW_SWAPPED;
+        }
+        return hr;
     }
     if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture,
surface->sub_resource_idx, &surface_dc)))
@@ -474,7 +491,7 @@ static HRESULT ddraw_surface_set_palette(struct ddraw_surface
*surface, IDirectD
             palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
         wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
                 palette_impl ? palette_impl->wined3d_palette : NULL);
-        ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
+        ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
     }
     if (palette_impl)
         IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
@@ -990,7 +1007,7 @@ static HRESULT surface_lock(struct ddraw_surface *surface,
     }
     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-        hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE);
+        hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0);
     if (SUCCEEDED(hr))
         hr =
wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture),
                 surface->sub_resource_idx, &map_desc, rect ? &box : NULL,
@@ -1179,7 +1196,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Unlock(IDirectDrawSurface
     wined3d_mutex_lock();
     hr =
wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture),
surface->sub_resource_idx);
     if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps &
DDSCAPS_PRIMARYSURFACE)
-        hr = ddraw_surface_update_frontbuffer(surface,
&surface->ddraw->primary_lock, FALSE);
+        hr = ddraw_surface_update_frontbuffer(surface,
&surface->ddraw->primary_lock, FALSE, 0);
     wined3d_mutex_unlock();
     return hr;
@@ -1224,6 +1241,24 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface1_Unlock(IDirectDrawSurface
     return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
 }
+static unsigned int ddraw_swap_interval_from_flags(DWORD flags)
+{
+    if (flags & DDFLIP_NOVSYNC)
+        return 0;
+
+    switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
+    {
+        case DDFLIP_INTERVAL2:
+            return 2;
+        case DDFLIP_INTERVAL3:
+            return 3;
+        case DDFLIP_INTERVAL4:
+            return 4;
+        default:
+            return 1;
+    }
+}
+
 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
         IDirectDrawSurface7 *src, DWORD flags)
 {
@@ -1337,7 +1372,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Flip(IDirectDrawSurface7
     wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
     src_impl->wined3d_texture = texture;
-    if (flags)
+    if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 |
DDFLIP_INTERVAL4))
     {
         static UINT once;
         if (!once++)
@@ -1347,7 +1382,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_Flip(IDirectDrawSurface7
     }
     if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-        hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE);
+        hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE,
ddraw_swap_interval_from_flags(flags));
     else
         hr = DD_OK;
@@ -1488,11 +1523,11 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface
*dst_surface, cons
     if (!dst_surface->clipper)
     {
         if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps &
DDSCAPS_PRIMARYSURFACE)
-            hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE);
+            hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0);
         if (SUCCEEDED(hr))
             hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface,
&src_rect, flags, fill_colour, fx, filter);
         if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps &
DDSCAPS_PRIMARYSURFACE))
-            hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE);
+            hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0);
         return hr;
     }
@@ -1535,7 +1570,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface
*dst_surface, cons
             if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
             {
-                if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface,
&src_rect_clipped, TRUE)))
+                if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface,
&src_rect_clipped, TRUE, 0)))
                     break;
             }
         }
@@ -1546,7 +1581,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface
*dst_surface, cons
         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         {
-            if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface,
&clip_rect[i], FALSE)))
+            if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface,
&clip_rect[i], FALSE, 0)))
                 break;
         }
     }
@@ -2219,7 +2254,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7
*iface, HDC *dc)
     if (surface->dc)
         hr = DDERR_DCALREADYCREATED;
     else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-        hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE);
+        hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0);
     if (SUCCEEDED(hr))
         hr = wined3d_texture_get_dc(surface->wined3d_texture,
surface->sub_resource_idx, dc);
@@ -2321,7 +2356,7 @@ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7
*iface, HDC h
     {
         surface->dc = NULL;
         if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-            hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
+            hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0);
     }
     wined3d_mutex_unlock();
@@ -4289,12 +4324,12 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH
ddraw_surface7_BltFast(IDirectDrawSurfac
     }
     if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-        hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE);
+        hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0);
     if (SUCCEEDED(hr))
         hr = wined3d_texture_blt(dst_impl->wined3d_texture,
dst_impl->sub_resource_idx, &dst_rect,
                 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect,
flags, NULL, WINED3D_TEXF_POINT);
     if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps &
DDSCAPS_PRIMARYSURFACE))
-        hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE);
+        hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0);
     wined3d_mutex_unlock();
     switch(hr)
diff --git a/dll/directx/wine/ddraw/utils.c b/dll/directx/wine/ddraw/utils.c
index 65f24dc13f..b0a028d4a5 100644
--- a/dll/directx/wine/ddraw/utils.c
+++ b/dll/directx/wine/ddraw/utils.c
@@ -570,7 +570,7 @@ unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags)
     unsigned int wined3d_flags;
     wined3d_flags = flags & handled;
-    if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS)))
+    if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS | DDLOCK_WRITEONLY)))
         wined3d_flags |= WINED3D_MAP_READ;
     if (!(flags & DDLOCK_READONLY))
         wined3d_flags |= WINED3D_MAP_WRITE;
@@ -578,7 +578,7 @@ unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags)
         wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
     if (flags & DDLOCK_NODIRTYUPDATE)
         wined3d_flags |= WINED3D_MAP_NO_DIRTY_UPDATE;
-    flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_NODIRTYUPDATE);
+    flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_WRITEONLY |
DDLOCK_NODIRTYUPDATE);
     if (flags)
         FIXME("Unhandled flags %#x.\n", flags);
diff --git a/dll/directx/wine/ddraw/viewport.c b/dll/directx/wine/ddraw/viewport.c
index 6ef3226c4d..f2caf20858 100644
--- a/dll/directx/wine/ddraw/viewport.c
+++ b/dll/directx/wine/ddraw/viewport.c
@@ -249,109 +249,118 @@ static HRESULT WINAPI d3d_viewport_Initialize(IDirect3DViewport3
*iface, IDirect
     return DDERR_ALREADYINITIALIZED;
 }
-/*****************************************************************************
- * IDirect3DViewport3::GetViewport
- *
- * Returns the viewport data assigned to this viewport interface
- *
- * Params:
- *  Data: Address to store the data
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Data is NULL
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_viewport_GetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT
*lpData)
+static HRESULT WINAPI d3d_viewport_GetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT
*vp)
 {
-    struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface);
-    DWORD dwSize;
+    struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
+    DWORD size;
+
+    TRACE("iface %p, vp %p.\n", iface, vp);
-    TRACE("iface %p, data %p.\n", iface, lpData);
+    if (!vp)
+        return DDERR_INVALIDPARAMS;
     wined3d_mutex_lock();
-    dwSize = lpData->dwSize;
-    if (!This->use_vp2)
-        memcpy(lpData, &(This->viewports.vp1), dwSize);
-    else {
+    size = vp->dwSize;
+    if (!viewport->use_vp2)
+    {
+        memcpy(vp, &viewport->viewports.vp1, size);
+    }
+    else
+    {
         D3DVIEWPORT vp1;
+
         vp1.dwSize = sizeof(vp1);
-        vp1.dwX = This->viewports.vp2.dwX;
-        vp1.dwY = This->viewports.vp2.dwY;
-        vp1.dwWidth = This->viewports.vp2.dwWidth;
-        vp1.dwHeight = This->viewports.vp2.dwHeight;
+        vp1.dwX = viewport->viewports.vp2.dwX;
+        vp1.dwY = viewport->viewports.vp2.dwY;
+        vp1.dwWidth = viewport->viewports.vp2.dwWidth;
+        vp1.dwHeight = viewport->viewports.vp2.dwHeight;
         vp1.dvMaxX = 0.0;
         vp1.dvMaxY = 0.0;
         vp1.dvScaleX = 0.0;
         vp1.dvScaleY = 0.0;
-        vp1.dvMinZ = This->viewports.vp2.dvMinZ;
-        vp1.dvMaxZ = This->viewports.vp2.dvMaxZ;
-        memcpy(lpData, &vp1, dwSize);
+        vp1.dvMinZ = viewport->viewports.vp2.dvMinZ;
+        vp1.dvMaxZ = viewport->viewports.vp2.dvMaxZ;
+        memcpy(vp, &vp1, size);
     }
     if (TRACE_ON(ddraw))
     {
         TRACE("  returning D3DVIEWPORT :\n");
-        _dump_D3DVIEWPORT(lpData);
+        _dump_D3DVIEWPORT(vp);
     }
     wined3d_mutex_unlock();
-    return DD_OK;
+    return D3D_OK;
 }
-/*****************************************************************************
- * IDirect3DViewport3::SetViewport
- *
- * Sets the viewport information for this interface
- *
- * Params:
- *  lpData: Viewport to set
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Data is NULL
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT
*lpData)
+static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT
*vp)
 {
-    struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface);
+    struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
+    struct d3d_device *device = viewport->active_device;
+    struct wined3d_sub_resource_desc rt_desc;
+    struct wined3d_rendertarget_view *rtv;
     IDirect3DViewport3 *current_viewport;
+    struct ddraw_surface *surface;
-    TRACE("iface %p, data %p.\n", iface, lpData);
+    TRACE("iface %p, vp %p.\n", iface, vp);
+
+    if (!vp)
+        return DDERR_INVALIDPARAMS;
     if (TRACE_ON(ddraw))
     {
         TRACE("  getting D3DVIEWPORT :\n");
-        _dump_D3DVIEWPORT(lpData);
+        _dump_D3DVIEWPORT(vp);
     }
-    wined3d_mutex_lock();
-
-    This->use_vp2 = 0;
-    memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
-    memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
+    if (!device)
+    {
+        WARN("Viewport not bound to a device, returning
D3DERR_VIEWPORTHASNODEVICE.\n");
+        return D3DERR_VIEWPORTHASNODEVICE;
+    }
-    /* Tests on two games show that these values are never used properly so override
-       them with proper ones :-)
-    */
-    This->viewports.vp1.dvMinZ = 0.0;
-    This->viewports.vp1.dvMaxZ = 1.0;
+    wined3d_mutex_lock();
-    if (This->active_device)
+    if (device->version > 1)
     {
-        IDirect3DDevice3 *d3d_device3 =
&This->active_device->IDirect3DDevice3_iface;
-        if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3,
¤t_viewport)))
+        if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
+        {
+            wined3d_mutex_unlock();
+            return DDERR_INVALIDCAPS;
+        }
+        surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
+        wined3d_texture_get_sub_resource_desc(surface->wined3d_texture,
surface->sub_resource_idx, &rt_desc);
+
+        if (vp->dwX > rt_desc.width || vp->dwWidth > rt_desc.width -
vp->dwX
+            || vp->dwY > rt_desc.height || vp->dwHeight > rt_desc.height -
vp->dwY)
         {
-            if (current_viewport == iface) viewport_activate(This, FALSE);
-            IDirect3DViewport3_Release(current_viewport);
+            WARN("Invalid viewport, returning DDERR_INVALIDPARAMS.\n");
+            wined3d_mutex_unlock();
+            return DDERR_INVALIDPARAMS;
         }
     }
+    viewport->use_vp2 = 0;
+    memset(&viewport->viewports.vp1, 0, sizeof(viewport->viewports.vp1));
+    memcpy(&viewport->viewports.vp1, vp, vp->dwSize);
+
+    /* Empirical testing on a couple of d3d1 games showed that these values
+     * should be ignored. */
+    viewport->viewports.vp1.dvMinZ = 0.0;
+    viewport->viewports.vp1.dvMaxZ = 1.0;
+
+    if
(SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
¤t_viewport)))
+    {
+        if (current_viewport == iface)
+            viewport_activate(viewport, FALSE);
+        IDirect3DViewport3_Release(current_viewport);
+    }
+
     wined3d_mutex_unlock();
-    return DD_OK;
+    return D3D_OK;
 }
 /*****************************************************************************
@@ -882,53 +891,44 @@ static HRESULT WINAPI d3d_viewport_NextLight(IDirect3DViewport3
*iface,
  * IDirect3DViewport2 Methods.
  *****************************************************************************/
-/*****************************************************************************
- * IDirect3DViewport3::GetViewport2
- *
- * Returns the currently set viewport in a D3DVIEWPORT2 structure.
- * Similar to IDirect3DViewport3::GetViewport
- *
- * Params:
- *  lpData: Pointer to the structure to fill
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if the viewport was set with
- *                      IDirect3DViewport3::SetViewport
- *  DDERR_INVALIDPARAMS if Data is NULL
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2
*lpData)
+static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2
*vp)
 {
-    struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface);
-    DWORD dwSize;
+    struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
+    DWORD size;
-    TRACE("iface %p, data %p.\n", iface, lpData);
+    TRACE("iface %p, vp %p.\n", iface, vp);
+
+    if (!vp)
+        return DDERR_INVALIDPARAMS;
     wined3d_mutex_lock();
-    dwSize = lpData->dwSize;
-    if (This->use_vp2)
-        memcpy(lpData, &(This->viewports.vp2), dwSize);
-    else {
+    size = vp->dwSize;
+    if (viewport->use_vp2)
+    {
+        memcpy(vp, &viewport->viewports.vp2, size);
+    }
+    else
+    {
         D3DVIEWPORT2 vp2;
+
         vp2.dwSize = sizeof(vp2);
-        vp2.dwX = This->viewports.vp1.dwX;
-        vp2.dwY = This->viewports.vp1.dwY;
-        vp2.dwWidth = This->viewports.vp1.dwWidth;
-        vp2.dwHeight = This->viewports.vp1.dwHeight;
+        vp2.dwX = viewport->viewports.vp1.dwX;
+        vp2.dwY = viewport->viewports.vp1.dwY;
+        vp2.dwWidth = viewport->viewports.vp1.dwWidth;
+        vp2.dwHeight = viewport->viewports.vp1.dwHeight;
         vp2.dvClipX = 0.0;
         vp2.dvClipY = 0.0;
         vp2.dvClipWidth = 0.0;
         vp2.dvClipHeight = 0.0;
-        vp2.dvMinZ = This->viewports.vp1.dvMinZ;
-        vp2.dvMaxZ = This->viewports.vp1.dvMaxZ;
-        memcpy(lpData, &vp2, dwSize);
+        vp2.dvMinZ = viewport->viewports.vp1.dvMinZ;
+        vp2.dvMaxZ = viewport->viewports.vp1.dvMaxZ;
+        memcpy(vp, &vp2, size);
     }
     if (TRACE_ON(ddraw))
     {
         TRACE("  returning D3DVIEWPORT2 :\n");
-        _dump_D3DVIEWPORT2(lpData);
+        _dump_D3DVIEWPORT2(vp);
     }
     wined3d_mutex_unlock();
@@ -936,47 +936,64 @@ static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3
*iface, D3DVI
     return D3D_OK;
 }
-/*****************************************************************************
- * IDirect3DViewport3::SetViewport2
- *
- * Sets the viewport from a D3DVIEWPORT2 structure
- *
- * Params:
- *  lpData: Viewport to set
- *
- * Returns:
- *  D3D_OK on success
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_viewport_SetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2
*lpData)
+static HRESULT WINAPI d3d_viewport_SetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2
*vp)
 {
-    struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface);
+    struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
+    struct d3d_device *device = viewport->active_device;
+    struct wined3d_sub_resource_desc rt_desc;
+    struct wined3d_rendertarget_view *rtv;
     IDirect3DViewport3 *current_viewport;
+    struct ddraw_surface *surface;
+
+    TRACE("iface %p, vp %p.\n", iface, vp);
-    TRACE("iface %p, data %p.\n", iface, lpData);
+    if (!vp)
+        return DDERR_INVALIDPARAMS;
     if (TRACE_ON(ddraw))
     {
         TRACE("  getting D3DVIEWPORT2 :\n");
-        _dump_D3DVIEWPORT2(lpData);
+        _dump_D3DVIEWPORT2(vp);
     }
-    wined3d_mutex_lock();
+    if (!device)
+    {
+        WARN("Viewport not bound to a device, returning
D3DERR_VIEWPORTHASNODEVICE.\n");
+        return D3DERR_VIEWPORTHASNODEVICE;
+    }
-    This->use_vp2 = 1;
-    memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
-    memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
+    wined3d_mutex_lock();
-    if (This->active_device)
+    if (device->version > 1)
     {
-        IDirect3DDevice3 *d3d_device3 =
&This->active_device->IDirect3DDevice3_iface;
-        if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3,
¤t_viewport)))
+        if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
+        {
+            wined3d_mutex_unlock();
+            return DDERR_INVALIDCAPS;
+        }
+        surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
+        wined3d_texture_get_sub_resource_desc(surface->wined3d_texture,
surface->sub_resource_idx, &rt_desc);
+
+        if (vp->dwX > rt_desc.width || vp->dwWidth > rt_desc.width -
vp->dwX
+            || vp->dwY > rt_desc.height || vp->dwHeight > rt_desc.height -
vp->dwY)
         {
-            if (current_viewport == iface) viewport_activate(This, FALSE);
-            IDirect3DViewport3_Release(current_viewport);
+            WARN("Invalid viewport, returning DDERR_INVALIDPARAMS.\n");
+            wined3d_mutex_unlock();
+            return DDERR_INVALIDPARAMS;
         }
     }
+    viewport->use_vp2 = 1;
+    memset(&viewport->viewports.vp2, 0, sizeof(viewport->viewports.vp2));
+    memcpy(&viewport->viewports.vp2, vp, vp->dwSize);
+
+    if
(SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
¤t_viewport)))
+    {
+        if (current_viewport == iface)
+            viewport_activate(viewport, FALSE);
+        IDirect3DViewport3_Release(current_viewport);
+    }
+
     wined3d_mutex_unlock();
     return D3D_OK;
diff --git a/dll/directx/wine/wined3d/arb_program_shader.c
b/dll/directx/wine/wined3d/arb_program_shader.c
index f86c167b60..4fbb3a59ec 100644
--- a/dll/directx/wine/wined3d/arb_program_shader.c
+++ b/dll/directx/wine/wined3d/arb_program_shader.c
@@ -611,7 +611,7 @@ static void shader_arb_vs_local_constants(const struct
arb_vs_compiled_shader *g
     unsigned char i;
     /* Upload the position fixup */
-    shader_get_position_fixup(context, state, position_fixup);
+    shader_get_position_fixup(context, state, 1, position_fixup);
     GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB,
gl_shader->pos_fixup, position_fixup));
     if (!gl_shader->num_int_consts) return;
@@ -1061,7 +1061,7 @@ static void shader_arb_get_register_name(const struct
wined3d_shader_instruction
                             /* This is better than nothing for now */
                             sprintf(register_name, "fragment.texcoord[%s +
%u]", rel_reg, reg->idx[0].offset);
                         }
-                        else if(ctx->cur_ps_args->super.vp_mode != vertexshader)
+                        else if(ctx->cur_ps_args->super.vp_mode !=
WINED3D_VP_MODE_SHADER)
                         {
                             /* This is problematic because we'd have to consult the
ctx->ps_input strings
                              * for where to find the varying. Some may be
"0.0", others can be texcoords or
@@ -1416,9 +1416,6 @@ static void shader_hw_sample(const struct wined3d_shader_instruction
*ins, DWORD
     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
     const char *mod;
     BOOL pshader =
shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
-    const struct wined3d_shader *shader;
-    const struct wined3d_device *device;
-    const struct wined3d_gl_info *gl_info;
     const char *tex_dst = dst_str;
     struct color_fixup_masks masks;
@@ -1432,12 +1429,8 @@ static void shader_hw_sample(const struct
wined3d_shader_instruction *ins, DWORD
             break;
         case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
-            shader = ins->ctx->shader;
-            device = shader->device;
-            gl_info = &device->adapter->gl_info;
-
             if (pshader && priv->cur_ps_args->super.np2_fixup & (1u
<< sampler_idx)
-                    && gl_info->supported[ARB_TEXTURE_RECTANGLE])
+                    &&
ins->ctx->gl_info->supported[ARB_TEXTURE_RECTANGLE])
                 tex_type = "RECT";
             else
                 tex_type = "2D";
@@ -3422,73 +3415,68 @@ static void init_ps_input(const struct wined3d_shader *shader,
     const char *semantic_name;
     DWORD semantic_idx;
-    switch(args->super.vp_mode)
-    {
-        case pretransformed:
-        case fixedfunction:
-            /* The pixelshader has to collect the varyings on its own. In any case
properly load
-             * color0 and color1. In the case of pretransformed vertices also load
texcoords. Set
-             * other attribs to 0.0.
-             *
-             * For fixedfunction this behavior is correct, according to the tests. For
pretransformed
-             * we'd either need a replacement shader that can load other attribs like
BINORMAL, or
-             * load the texcoord attrib pointers to match the pixel shader signature
-             */
-            for (i = 0; i < shader->input_signature.element_count; ++i)
-            {
-                input = &shader->input_signature.elements[i];
-                if (!(semantic_name = input->semantic_name))
-                    continue;
-                semantic_idx = input->semantic_idx;
+    if (args->super.vp_mode == WINED3D_VP_MODE_SHADER)
+    {
+        /* That one is easy. The vertex shaders provide v0-v7 in
+         * fragment.texcoord and v8 and v9 in fragment.color. */
+        for (i = 0; i < 8; ++i)
+        {
+            priv->ps_input[i] = texcoords[i];
+        }
+        priv->ps_input[8] = "fragment.color.primary";
+        priv->ps_input[9] = "fragment.color.secondary";
+        return;
+    }
-                if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
-                {
-                    if (!semantic_idx)
-                        priv->ps_input[input->register_idx] =
"fragment.color.primary";
-                    else if (semantic_idx == 1)
-                        priv->ps_input[input->register_idx] =
"fragment.color.secondary";
-                    else
-                        priv->ps_input[input->register_idx] = "0.0";
-                }
-                else if (args->super.vp_mode == fixedfunction)
-                {
-                    priv->ps_input[input->register_idx] = "0.0";
-                }
-                else if (shader_match_semantic(semantic_name,
WINED3D_DECL_USAGE_TEXCOORD))
-                {
-                    if (semantic_idx < 8)
-                        priv->ps_input[input->register_idx] =
texcoords[semantic_idx];
-                    else
-                        priv->ps_input[input->register_idx] = "0.0";
-                }
-                else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
-                {
-                    if (!semantic_idx)
-                        priv->ps_input[input->register_idx] =
"fragment.fogcoord";
-                    else
-                        priv->ps_input[input->register_idx] = "0.0";
-                }
-                else
-                {
-                    priv->ps_input[input->register_idx] = "0.0";
-                }
+    /* The fragment shader has to collect the varyings on its own. In any case
+     * properly load color0 and color1. In the case of pre-transformed
+     * vertices also load texture coordinates. Set other attributes to 0.0.
+     *
+     * For fixed-function this behavior is correct, according to the tests.
+     * For pre-transformed we'd either need a replacement shader that can load
+     * other attributes like BINORMAL, or load the texture coordinate
+     * attribute pointers to match the fragment shader signature. */
+    for (i = 0; i < shader->input_signature.element_count; ++i)
+    {
+        input = &shader->input_signature.elements[i];
+        if (!(semantic_name = input->semantic_name))
+            continue;
+        semantic_idx = input->semantic_idx;
-                TRACE("v%u, semantic %s%u is %s\n", input->register_idx,
-                        semantic_name, semantic_idx,
priv->ps_input[input->register_idx]);
-            }
-            break;
+        if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+        {
+            if (!semantic_idx)
+                priv->ps_input[input->register_idx] =
"fragment.color.primary";
+            else if (semantic_idx == 1)
+                priv->ps_input[input->register_idx] =
"fragment.color.secondary";
+            else
+                priv->ps_input[input->register_idx] = "0.0";
+        }
+        else if (args->super.vp_mode == WINED3D_VP_MODE_FF)
+        {
+            priv->ps_input[input->register_idx] = "0.0";
+        }
+        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+        {
+            if (semantic_idx < 8)
+                priv->ps_input[input->register_idx] = texcoords[semantic_idx];
+            else
+                priv->ps_input[input->register_idx] = "0.0";
+        }
+        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+        {
+            if (!semantic_idx)
+                priv->ps_input[input->register_idx] =
"fragment.fogcoord";
+            else
+                priv->ps_input[input->register_idx] = "0.0";
+        }
+        else
+        {
+            priv->ps_input[input->register_idx] = "0.0";
+        }
-        case vertexshader:
-            /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord
and v8 and v9 in
-             * fragment.color
-             */
-            for(i = 0; i < 8; i++)
-            {
-                priv->ps_input[i] = texcoords[i];
-            }
-            priv->ps_input[8] = "fragment.color.primary";
-            priv->ps_input[9] = "fragment.color.secondary";
-            break;
+        TRACE("v%u, semantic %s%u is %s\n", input->register_idx,
+                semantic_name, semantic_idx, priv->ps_input[input->register_idx]);
     }
 }
@@ -6084,17 +6072,19 @@ static const char *get_argreg(struct wined3d_string_buffer
*buffer, DWORD argnum
 }
 static void gen_ffp_instr(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL
color,
-        BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
+        BOOL alpha, BOOL tmp_dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
 {
     const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
     unsigned int mul = 1;
-    if(color && alpha) dstmask = "";
-    else if(color) dstmask = ".xyz";
-    else dstmask = ".w";
+    if (color && alpha)
+        dstmask = "";
+    else if (color)
+        dstmask = ".xyz";
+    else
+        dstmask = ".w";
-    if(dst == tempreg) dstreg = "tempreg";
-    else dstreg = "ret";
+    dstreg = tmp_dst ? "tempreg" : "ret";
     arg0 = get_argreg(buffer, 0, stage, dw_arg0);
     arg1 = get_argreg(buffer, 1, stage, dw_arg1);
@@ -6273,7 +6263,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings
*settings, con
         if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 ==
WINED3DTA_TEXTURE)
             tex_read |= 1u << stage;
-        if (settings->op[stage].dst == tempreg)
+        if (settings->op[stage].tmp_dst)
             tempreg_used = TRUE;
         if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
             tempreg_used = TRUE;
@@ -6391,12 +6381,17 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings
*settings, con
         textype = arbfp_texture_target(settings->op[stage].tex_type);
-        if(settings->op[stage].projected == proj_none) {
+        if (settings->op[stage].projected == WINED3D_PROJECTION_NONE)
+        {
             instr = "TEX";
-        } else if(settings->op[stage].projected == proj_count4 ||
-                  settings->op[stage].projected == proj_count3) {
+        }
+        else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4
+                || settings->op[stage].projected == WINED3D_PROJECTION_COUNT3)
+        {
             instr = "TXP";
-        } else {
+        }
+        else
+        {
             FIXME("Unexpected projection mode %d\n",
settings->op[stage].projected);
             instr = "TXP";
         }
@@ -6410,18 +6405,27 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings
*settings, con
             shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n",
stage - 1);
             shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage -
1);
-            /* with projective textures, texbem only divides the static texture coord,
not the displacement,
-             * so multiply the displacement with the dividing parameter before passing it
to TXP
-             */
-            if (settings->op[stage].projected != proj_none) {
-                if(settings->op[stage].projected == proj_count4) {
+            /* With projective textures, texbem only divides the static
+             * texture coordinate, not the displacement, so multiply the
+             * displacement with the dividing parameter before passing it to
+             * TXP. */
+            if (settings->op[stage].projected != WINED3D_PROJECTION_NONE)
+            {
+                if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4)
+                {
                     shader_addline(&buffer, "MOV ret.w,
fragment.texcoord[%u].w;\n", stage);
-                    shader_addline(&buffer, "MUL ret.xyz, ret,
fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
-                } else {
+                    shader_addline(&buffer, "MUL ret.xyz, ret,
fragment.texcoord[%u].w, fragment.texcoord[%u];\n",
+                            stage, stage);
+                }
+                else
+                {
                     shader_addline(&buffer, "MOV ret.w,
fragment.texcoord[%u].z;\n", stage);
-                    shader_addline(&buffer, "MAD ret.xyz, ret,
fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
+                    shader_addline(&buffer, "MAD ret.xyz, ret,
fragment.texcoord[%u].z, fragment.texcoord[%u];\n",
+                            stage, stage);
                 }
-            } else {
+            }
+            else
+            {
                 shader_addline(&buffer, "ADD ret, ret,
fragment.texcoord[%u];\n", stage);
             }
@@ -6433,12 +6437,16 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings
*settings, con
                                stage - 1, stage - 1, stage - 1);
                 shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n",
stage, stage);
             }
-        } else if(settings->op[stage].projected == proj_count3) {
+        }
+        else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT3)
+        {
             shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n",
stage);
             shader_addline(&buffer, "MOV ret.w, ret.z;\n");
             shader_addline(&buffer, "%s tex%u, ret, texture[%u], %s;\n",
                             instr, stage, stage, textype);
-        } else {
+        }
+        else
+        {
             shader_addline(&buffer, "%s tex%u, fragment.texcoord[%u],
texture[%u], %s;\n",
                             instr, stage, stage, stage, textype);
         }
@@ -6487,23 +6495,23 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings
*settings, con
         if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
         {
-            gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+            gen_ffp_instr(&buffer, stage, TRUE, FALSE,
settings->op[stage].tmp_dst,
                           settings->op[stage].cop, settings->op[stage].carg0,
                           settings->op[stage].carg1, settings->op[stage].carg2);
         }
         else if (op_equal)
         {
-            gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
+            gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].tmp_dst,
                           settings->op[stage].cop, settings->op[stage].carg0,
                           settings->op[stage].carg1, settings->op[stage].carg2);
         }
         else if (settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP
                 && settings->op[stage].cop !=
WINED3D_TOP_BUMPENVMAP_LUMINANCE)
         {
-            gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+            gen_ffp_instr(&buffer, stage, TRUE, FALSE,
settings->op[stage].tmp_dst,
                           settings->op[stage].cop, settings->op[stage].carg0,
                           settings->op[stage].carg1, settings->op[stage].carg2);
-            gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst,
+            gen_ffp_instr(&buffer, stage, FALSE, TRUE,
settings->op[stage].tmp_dst,
                           settings->op[stage].aop, settings->op[stage].aarg0,
                           settings->op[stage].aarg1, settings->op[stage].aarg2);
         }
@@ -6928,8 +6936,8 @@ static void arbfp_blitter_destroy(struct wined3d_blitter *blitter,
struct wined3
     heap_free(arbfp_blitter);
 }
-static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const struct
arbfp_blit_type *type,
-        char *luminance)
+static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer,
+        const struct arbfp_blit_type *type, char *luminance)
 {
     char chroma;
     const char *tex, *texinstr = "TXP";
@@ -6977,13 +6985,12 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer
*buffer, const stru
     shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
     shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");
-    /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for
the
-     * even and odd pixels respectively
-     */
+    /* Multiply the x coordinate by 0.5 and get the fraction. This gives 0.25
+     * and 0.75 for the even and odd pixels respectively. */
     shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n");
     shader_addline(buffer, "FRC texcrd2, texcrd2;\n");
-    /* Sample Pixel 1 */
+    /* Sample Pixel 1. */
     shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr,
tex);
     /* Put the value into either of the chroma values */
@@ -7012,12 +7019,10 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer
*buffer, const stru
     /* This gives the correctly filtered luminance value */
     shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0],
%s;\n", tex);
-
-    return TRUE;
 }
-static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct
arbfp_blit_type *type,
-        char *luminance)
+static void gen_yv12_read(struct wined3d_string_buffer *buffer,
+        const struct arbfp_blit_type *type, char *luminance)
 {
     const char *tex;
     static const float yv12_coef[]
@@ -7079,7 +7084,6 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer,
const struct arb
      */
     if (type->res_type == WINED3D_GL_RES_TYPE_TEX_2D)
     {
-
         shader_addline(buffer, "RCP chroma.w, size.y;\n");
         shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n");
@@ -7087,7 +7091,7 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer,
const struct arb
         shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n");
         shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y,
yv12_coef.x;\n");
-        /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+        /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */
         shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /*
To avoid 0.5 == 0.5 comparisons */
         shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
         shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
@@ -7101,11 +7105,11 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer,
const struct arb
     }
     else
     {
-        /* Read from [size - size+size/4] */
+        /* The y coordinate for V is in the range [size, size + size / 4). */
         shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
         shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n");
-        /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+        /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */
         shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /*
To avoid 0.5 == 0.5 comparisons */
         shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
         shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
@@ -7161,12 +7165,10 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer,
const struct arb
         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n",
tex);
     }
     *luminance = 'a';
-
-    return TRUE;
 }
-static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct
arbfp_blit_type *type,
-        char *luminance)
+static void gen_nv12_read(struct wined3d_string_buffer *buffer,
+        const struct arbfp_blit_type *type, char *luminance)
 {
     const char *tex;
     static const float nv12_coef[]
@@ -7242,7 +7244,7 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer,
const struct arb
     }
     else
     {
-        /* Read from [size - size+size/2] */
+        /* The y coordinate for chroma is in the range [size, size + size / 2). */
         shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.y, size.y;\n");
         shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
@@ -7297,8 +7299,6 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer,
const struct arb
         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n",
tex);
     }
     *luminance = 'a';
-
-    return TRUE;
 }
 /* Context activation is done by the caller. */
@@ -7464,27 +7464,15 @@ static GLuint gen_yuv_shader(const struct wined3d_gl_info
*gl_info, const struct
     {
         case COMPLEX_FIXUP_UYVY:
         case COMPLEX_FIXUP_YUY2:
-            if (!gen_planar_yuv_read(&buffer, type, &luminance_component))
-            {
-                string_buffer_free(&buffer);
-                return 0;
-            }
+            gen_packed_yuv_read(&buffer, type, &luminance_component);
             break;
         case COMPLEX_FIXUP_YV12:
-            if (!gen_yv12_read(&buffer, type, &luminance_component))
-            {
-                string_buffer_free(&buffer);
-                return 0;
-            }
+            gen_yv12_read(&buffer, type, &luminance_component);
             break;
         case COMPLEX_FIXUP_NV12:
-            if (!gen_nv12_read(&buffer, type, &luminance_component))
-            {
-                string_buffer_free(&buffer);
-                return 0;
-            }
+            gen_nv12_read(&buffer, type, &luminance_component);
             break;
         default:
@@ -7710,7 +7698,7 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op, const
struct wine
     enum complex_fixup src_fixup;
     BOOL decompress;
-    if (!context->gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
         return FALSE;
     if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id ==
src_format->id)
@@ -7795,59 +7783,105 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op,
const struct wine
 }
 static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
-        struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD
src_location,
-        const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location,
const RECT *dst_rect,
+        struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned
int src_sub_resource_idx,
+        DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+        unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
         const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type
filter)
 {
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    struct wined3d_texture *src_texture = src_surface->container;
-    struct wined3d_texture *dst_texture = dst_surface->container;
     struct wined3d_device *device = dst_texture->resource.device;
+    struct wined3d_texture *staging_texture = NULL;
     struct wined3d_arbfp_blitter *arbfp_blitter;
     struct wined3d_color_key alpha_test_key;
     struct wined3d_blitter *next;
+    unsigned int src_level;
     RECT s, d;
+    TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u,
src_location %s, src_rect %s, "
+            "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s,
colour_key %p, filter %s.\n",
+            blitter, op, context, src_texture, src_sub_resource_idx,
wined3d_debug_location(src_location),
+            wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx,
wined3d_debug_location(dst_location),
+            wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter));
+
     if (!arbfp_blit_supported(op, context, &src_texture->resource, src_location,
             &dst_texture->resource, dst_location))
     {
-        if ((next = blitter->next))
-            return next->ops->blitter_blit(next, op, context, src_surface,
src_location,
-                    src_rect, dst_surface, dst_location, dst_rect, color_key, filter);
+        if (!(next = blitter->next))
+        {
+            ERR("No blitter to handle blit op %#x.\n", op);
+            return dst_location;
+        }
+
+        TRACE("Forwarding to blitter %p.\n", next);
+        return next->ops->blitter_blit(next, op, context, src_texture,
src_sub_resource_idx, src_location,
+                src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect,
color_key, filter);
     }
     arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter);
-    /* Now load the surface */
-    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-            && (surface_get_sub_resource(src_surface)->locations
-            & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
-            == WINED3D_LOCATION_DRAWABLE
+    if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+    {
+        struct wined3d_resource_desc desc;
+        struct wined3d_box upload_box;
+        HRESULT hr;
+
+        TRACE("Source texture is not GPU accessible, creating a staging
texture.\n");
+
+        src_level = src_sub_resource_idx % src_texture->level_count;
+        desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+        desc.format = src_texture->resource.format->id;
+        desc.multisample_type = src_texture->resource.multisample_type;
+        desc.multisample_quality = src_texture->resource.multisample_quality;
+        desc.usage = WINED3DUSAGE_PRIVATE;
+        desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+        desc.width = wined3d_texture_get_level_width(src_texture, src_level);
+        desc.height = wined3d_texture_get_level_height(src_texture, src_level);
+        desc.depth = 1;
+        desc.size = 0;
+
+        if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
+                NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
+        {
+            ERR("Failed to create staging texture, hr %#x.\n", hr);
+            return dst_location;
+        }
+
+        wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
+        wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
+                src_texture, src_sub_resource_idx, &upload_box);
+
+        src_texture = staging_texture;
+        src_sub_resource_idx = 0;
+    }
+    else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            && (src_texture->sub_resources[src_sub_resource_idx].locations
+            & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) ==
WINED3D_LOCATION_DRAWABLE
             && !wined3d_resource_is_offscreen(&src_texture->resource))
     {
-        unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
         /* Without FBO blits transferring from the drawable to the texture is
          * expensive, because we have to flip the data in sysmem. Since we can
          * 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, context);
+        texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context);
         s = *src_rect;
+        src_level = src_sub_resource_idx % src_texture->level_count;
         s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top;
         s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom;
         src_rect = &s;
     }
     else
+    {
         wined3d_texture_load(src_texture, context, FALSE);
+    }
-    context_apply_blit_state(context, device);
+    context_apply_ffp_blit_state(context, device);
     if (dst_location == WINED3D_LOCATION_DRAWABLE)
     {
         d = *dst_rect;
-        surface_translate_drawable_coords(dst_surface, context->win_handle, &d);
+        wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle,
&d);
         dst_rect = &d;
     }
@@ -7857,15 +7891,16 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter,
enum wined3d_bl
         if (dst_location == WINED3D_LOCATION_DRAWABLE)
         {
-            TRACE("Destination surface %p is onscreen.\n", dst_surface);
+            TRACE("Destination texture %p is onscreen.\n", dst_texture);
             buffer = wined3d_texture_get_gl_buffer(dst_texture);
         }
         else
         {
-            TRACE("Destination surface %p is offscreen.\n", dst_surface);
+            TRACE("Destination texture %p is offscreen.\n", dst_texture);
             buffer = GL_COLOR_ATTACHMENT0;
         }
-        context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL,
dst_location);
+        context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER,
+                &dst_texture->resource, dst_sub_resource_idx, NULL, 0,
dst_location);
         context_set_draw_buffer(context, buffer);
         context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
         context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -7882,14 +7917,16 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter,
enum wined3d_bl
     arbfp_blit_set(arbfp_blitter, context, src_texture, src_sub_resource_idx, color_key);
     /* Draw a textured quad */
-    draw_textured_quad(src_texture, src_sub_resource_idx, context, src_rect, dst_rect,
filter);
+    context_draw_textured_quad(context, src_texture, src_sub_resource_idx, src_rect,
dst_rect, filter);
     /* Leave the opengl state valid for blitting */
     arbfp_blit_unset(context->gl_info);
-    if (wined3d_settings.strict_draw_ordering
-            || (dst_texture->swapchain &&
(dst_texture->swapchain->front_buffer == dst_texture)))
-        context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across
contexts. */
+    if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer
== dst_texture))
+        context->gl_info->gl_ops.gl.p_glFlush();
+
+    if (staging_texture)
+        wined3d_texture_decref(staging_texture);
     return dst_location;
 }
diff --git a/dll/directx/wine/wined3d/ati_fragment_shader.c
b/dll/directx/wine/wined3d/ati_fragment_shader.c
index 9d6837a2f2..9a1cae34cd 100644
--- a/dll/directx/wine/wined3d/ati_fragment_shader.c
+++ b/dll/directx/wine/wined3d/ati_fragment_shader.c
@@ -341,9 +341,8 @@ static GLuint find_tmpreg(const struct texture_stage_op
op[MAX_TEXTURES])
             lowest_read = i;
         }
-        if(lowest_write == -1 && op[i].dst == tempreg) {
+        if (lowest_write == -1 && op[i].tmp_dst)
             lowest_write = i;
-        }
         if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE ||
op[i].carg0 == WINED3DTA_TEXTURE ||
            op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE ||
op[i].aarg0 == WINED3DTA_TEXTURE) {
@@ -505,16 +504,13 @@ static GLuint gen_ati_shader(const struct texture_stage_op
op[MAX_TEXTURES],
         TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB,
GL_SWIZZLE_STR_ATI)\n",
               stage, stage);
-        GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
-                   GL_TEXTURE0_ARB + stage,
-                   GL_SWIZZLE_STR_ATI));
-        if(op[stage + 1].projected == proj_none) {
+        GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, GL_TEXTURE0_ARB + stage,
GL_SWIZZLE_STR_ATI));
+        if (op[stage + 1].projected == WINED3D_PROJECTION_NONE)
             swizzle = GL_SWIZZLE_STR_ATI;
-        } else if(op[stage + 1].projected == proj_count4) {
+        else if (op[stage + 1].projected == WINED3D_PROJECTION_COUNT4)
             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
-        } else {
+        else
             swizzle = GL_SWIZZLE_STR_DR_ATI;
-        }
         TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
               stage + 1, stage + 1, debug_swizzle(swizzle));
         GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
@@ -579,13 +575,12 @@ static GLuint gen_ati_shader(const struct texture_stage_op
op[MAX_TEXTURES],
         if (op[stage].cop == WINED3D_TOP_DISABLE)
             break;
-        if(op[stage].projected == proj_none) {
+        if (op[stage].projected == WINED3D_PROJECTION_NONE)
             swizzle = GL_SWIZZLE_STR_ATI;
-        } else if(op[stage].projected == proj_count3) {
+        else if (op[stage].projected == WINED3D_PROJECTION_COUNT3)
             swizzle = GL_SWIZZLE_STR_DR_ATI;
-        } else {
+        else
             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
-        }
         if (op_reads_texture(&op[stage]))
         {
@@ -624,14 +619,18 @@ static GLuint gen_ati_shader(const struct texture_stage_op
op[MAX_TEXTURES],
             break;
         }
-        if(op[stage].dst == tempreg) {
-            /* If we're writing to D3DTA_TEMP, but never reading from it we don't
have to write there in the first place.
-             * skip the entire stage, this saves some GPU time
-             */
-            if(tmparg == GL_NONE) continue;
+        if (op[stage].tmp_dst)
+        {
+            /* If we're writing to D3DTA_TEMP, but never reading from it we
+             * don't have to write there in the first place. Skip the entire
+             * stage, this saves some GPU time. */
+            if (tmparg == GL_NONE)
+                continue;
             dstreg = tmparg;
-        } else {
+        }
+        else
+        {
             dstreg = GL_REG_0_ATI;
         }
diff --git a/dll/directx/wine/wined3d/buffer.c b/dll/directx/wine/wined3d/buffer.c
index cae7ef8788..9baf0556dd 100644
--- a/dll/directx/wine/wined3d/buffer.c
+++ b/dll/directx/wine/wined3d/buffer.c
@@ -615,10 +615,7 @@ static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer
*buffer,
                 return TRUE;
             if (!wined3d_resource_allocate_sysmem(&buffer->resource))
-            {
-                ERR("Failed to allocate system memory.\n");
                 return FALSE;
-            }
             return TRUE;
         case WINED3D_LOCATION_BUFFER:
@@ -1183,8 +1180,6 @@ static void wined3d_buffer_unmap(struct wined3d_buffer *buffer)
         }
         GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint));
-        if (wined3d_settings.strict_draw_ordering)
-            gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across
contexts. */
         context_release(context);
         buffer_clear_dirty_areas(buffer);
@@ -1380,6 +1375,9 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct
wined3d_device
     buffer->bind_flags = bind_flags;
     buffer->locations = WINED3D_LOCATION_SYSMEM;
+    if (!wined3d_resource_allocate_sysmem(&buffer->resource))
+        return E_OUTOFMEMORY;
+
     TRACE("buffer %p, size %#x, usage %#x, format %s, memory @ %p.\n",
             buffer, buffer->resource.size, buffer->resource.usage,
             debug_d3dformat(buffer->resource.format->id),
buffer->resource.heap_memory);
@@ -1428,7 +1426,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct
wined3d_device
     if (data)
         wined3d_device_update_sub_resource(device, &buffer->resource,
-                0, NULL, data->data, data->row_pitch, data->slice_pitch);
+                0, NULL, data->data, data->row_pitch, data->slice_pitch, 0);
     return WINED3D_OK;
 }
diff --git a/dll/directx/wine/wined3d/context.c b/dll/directx/wine/wined3d/context.c
index 8a8d952c3f..0ee5b65bc1 100644
--- a/dll/directx/wine/wined3d/context.c
+++ b/dll/directx/wine/wined3d/context.c
@@ -148,8 +148,8 @@ static void context_attach_gl_texture_fbo(struct wined3d_context
*context,
         gl_info->fbo_ops.glFramebufferTexture(fbo_target, attachment,
                 resource->object, resource->level);
     }
-    else if (resource->target == GL_TEXTURE_1D_ARRAY || resource->target ==
GL_TEXTURE_2D_ARRAY ||
-            resource->target == GL_TEXTURE_3D)
+    else if (resource->target == GL_TEXTURE_1D_ARRAY || resource->target ==
GL_TEXTURE_2D_ARRAY
+            || resource->target == GL_TEXTURE_3D)
     {
         if (!gl_info->fbo_ops.glFramebufferTextureLayer)
         {
@@ -164,7 +164,6 @@ static void context_attach_gl_texture_fbo(struct wined3d_context
*context,
     {
         gl_info->fbo_ops.glFramebufferTexture1D(fbo_target, attachment,
                 resource->target, resource->object, resource->level);
-        checkGLcall("glFramebufferTexture1D()");
     }
     else
     {
@@ -253,6 +252,8 @@ static void context_dump_fbo_attachment(const struct wined3d_gl_info
*gl_info, G
     }
     texture_type[] =
     {
+        {GL_TEXTURE_1D,                   GL_TEXTURE_BINDING_1D,
"1d",          WINED3D_GL_EXT_NONE},
+        {GL_TEXTURE_1D_ARRAY,             GL_TEXTURE_BINDING_1D_ARRAY,
"1d-array",    EXT_TEXTURE_ARRAY},
         {GL_TEXTURE_2D,                   GL_TEXTURE_BINDING_2D,
"2d",          WINED3D_GL_EXT_NONE},
         {GL_TEXTURE_RECTANGLE_ARB,        GL_TEXTURE_BINDING_RECTANGLE_ARB,
"rectangle",   ARB_TEXTURE_RECTANGLE},
         {GL_TEXTURE_2D_ARRAY,             GL_TEXTURE_BINDING_2D_ARRAY,
"2d-array" ,   EXT_TEXTURE_ARRAY},
@@ -456,19 +457,15 @@ static inline void context_set_fbo_key_for_render_target(const
struct wined3d_co
     }
     texture = wined3d_texture_from_resource(resource);
-    if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
+    if (texture->current_renderbuffer)
     {
-        struct wined3d_surface *surface =
texture->sub_resources[sub_resource_idx].u.surface;
-
-        if (surface->current_renderbuffer)
-        {
-            key->objects[idx].object = surface->current_renderbuffer->id;
-            key->objects[idx].target = 0;
-            key->objects[idx].level = key->objects[idx].layer = 0;
-            key->rb_namespace |= 1 << idx;
-            return;
-        }
+        key->objects[idx].object = texture->current_renderbuffer->id;
+        key->objects[idx].target = 0;
+        key->objects[idx].level = key->objects[idx].layer = 0;
+        key->rb_namespace |= 1 << idx;
+        return;
     }
+
     key->objects[idx].target = wined3d_texture_get_sub_resource_target(texture,
sub_resource_idx);
     key->objects[idx].level = sub_resource_idx % texture->level_count;
     key->objects[idx].layer = sub_resource_idx / texture->level_count;
@@ -615,10 +612,7 @@ static struct fbo_entry *context_find_fbo_entry(struct
wined3d_context *context,
         }
         else if (depth_stencil->resource->type == WINED3D_RTYPE_TEXTURE_2D)
         {
-            struct wined3d_surface *surface;
-
-            surface =
ds_texture->sub_resources[depth_stencil->sub_resource_idx].u.surface;
-            surface_set_compatible_renderbuffer(surface, &render_targets[0]);
+            wined3d_texture_set_compatible_renderbuffer(ds_texture, ds_level,
&render_targets[0]);
         }
     }
@@ -761,8 +755,8 @@ static void context_apply_fbo_entry(struct wined3d_context *context,
GLenum targ
 /* Context activation is done by the caller. */
 static void context_apply_fbo_state(struct wined3d_context *context, GLenum target,
-        struct wined3d_rendertarget_info *render_targets, struct wined3d_surface
*depth_stencil,
-        DWORD color_location, DWORD ds_location)
+        const struct wined3d_rendertarget_info *render_targets,
+        const struct wined3d_rendertarget_info *depth_stencil, DWORD color_location,
DWORD ds_location)
 {
     struct fbo_entry *entry, *entry2;
@@ -784,32 +778,35 @@ static void context_apply_fbo_state(struct wined3d_context *context,
GLenum targ
     }
     else
     {
-        struct wined3d_rendertarget_info ds = {{0}};
-
-        if (depth_stencil)
-        {
-            ds.resource = &depth_stencil->container->resource;
-            ds.sub_resource_idx = surface_get_sub_resource_idx(depth_stencil);
-            ds.layer_count = 1;
-        }
         context->current_fbo = context_find_fbo_entry(context, target,
-                render_targets, &ds, color_location, ds_location);
+                render_targets, depth_stencil, color_location, ds_location);
         context_apply_fbo_entry(context, target, context->current_fbo);
     }
 }
 /* Context activation is done by the caller. */
 void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
-        struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil,
DWORD location)
+        struct wined3d_resource *rt, unsigned int rt_sub_resource_idx,
+        struct wined3d_resource *ds, unsigned int ds_sub_resource_idx, DWORD location)
 {
+    struct wined3d_rendertarget_info ds_info = {{0}};
+
     memset(context->blit_targets, 0, sizeof(context->blit_targets));
-    if (render_target)
+    if (rt)
     {
-        context->blit_targets[0].resource =
&render_target->container->resource;
-        context->blit_targets[0].sub_resource_idx =
surface_get_sub_resource_idx(render_target);
+        context->blit_targets[0].resource = rt;
+        context->blit_targets[0].sub_resource_idx = rt_sub_resource_idx;
         context->blit_targets[0].layer_count = 1;
     }
-    context_apply_fbo_state(context, target, context->blit_targets, depth_stencil,
location, location);
+
+    if (ds)
+    {
+        ds_info.resource = ds;
+        ds_info.sub_resource_idx = ds_sub_resource_idx;
+        ds_info.layer_count = 1;
+    }
+
+    context_apply_fbo_state(context, target, context->blit_targets, &ds_info,
location, location);
 }
 /* Context activation is done by the caller. */
@@ -1070,34 +1067,22 @@ static void context_queue_fbo_entry_destruction(struct
wined3d_context *context,
     list_add_head(&context->fbo_destroy_list, &entry->entry);
 }
-void context_resource_released(const struct wined3d_device *device,
-        struct wined3d_resource *resource, enum wined3d_resource_type type)
+void context_resource_released(const struct wined3d_device *device, struct
wined3d_resource *resource)
 {
-    struct wined3d_texture *texture;
-    UINT i;
+    unsigned int i;
     if (!device->d3d_initialized)
         return;
-    switch (type)
+    for (i = 0; i < device->context_count; ++i)
     {
-        case WINED3D_RTYPE_TEXTURE_2D:
-        case WINED3D_RTYPE_TEXTURE_3D:
-            texture = texture_from_resource(resource);
-
-            for (i = 0; i < device->context_count; ++i)
-            {
-                struct wined3d_context *context = device->contexts[i];
-                if (context->current_rt.texture == texture)
-                {
-                    context->current_rt.texture = NULL;
-                    context->current_rt.sub_resource_idx = 0;
-                }
-            }
-            break;
+        struct wined3d_context *context = device->contexts[i];
-        default:
-            break;
+        if (&context->current_rt.texture->resource == resource)
+        {
+            context->current_rt.texture = NULL;
+            context->current_rt.sub_resource_idx = 0;
+        }
     }
 }
@@ -1107,7 +1092,7 @@ void context_gl_resource_released(struct wined3d_device *device,
     context_enum_fbo_entries(device, name, rb_namespace,
context_queue_fbo_entry_destruction);
 }
-void context_surface_update(struct wined3d_context *context, const struct wined3d_surface
*surface)
+void context_texture_update(struct wined3d_context *context, const struct wined3d_texture
*texture)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct fbo_entry *entry = context->current_fbo;
@@ -1117,10 +1102,10 @@ void context_surface_update(struct wined3d_context *context, const
struct wined3
     for (i = 0; i < gl_info->limits.buffers + 1; ++i)
     {
-        if (surface->container->texture_rgb.name == entry->key.objects[i].object
-                || surface->container->texture_srgb.name ==
entry->key.objects[i].object)
+        if (texture->texture_rgb.name == entry->key.objects[i].object
+                || texture->texture_srgb.name == entry->key.objects[i].object)
         {
-            TRACE("Updated surface %p is bound as attachment %u to the current
FBO.\n", surface, i);
+            TRACE("Updated texture %p is bound as attachment %u to the current
FBO.\n", texture, i);
             context->rebind_fbo = TRUE;
             return;
         }
@@ -1466,6 +1451,9 @@ static void context_destroy_gl_resources(struct wined3d_context
*context)
             }
         }
+        if (context->blit_vbo)
+            GL_EXTCALL(glDeleteBuffers(1, &context->blit_vbo));
+
         checkGLcall("context cleanup");
     }
@@ -1603,14 +1591,12 @@ 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)
+void context_restore(struct wined3d_context *context, struct wined3d_texture *texture,
unsigned int sub_resource_idx)
 {
-    if (context->current_rt.texture != restore->container
-            || context->current_rt.sub_resource_idx !=
surface_get_sub_resource_idx(restore))
+    if (context->current_rt.texture != texture ||
context->current_rt.sub_resource_idx != sub_resource_idx)
     {
         context_release(context);
-        context = context_acquire(restore->container->resource.device,
-                restore->container, surface_get_sub_resource_idx(restore));
+        context = context_acquire(texture->resource.device, texture,
sub_resource_idx);
     }
     context_release(context);
@@ -1791,6 +1777,7 @@ void context_bind_dummy_textures(const struct wined3d_device
*device, const stru
             gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY,
textures->tex_1d_array);
             gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY,
textures->tex_2d_array);
         }
+
         if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
             gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER,
textures->tex_buffer);
@@ -1866,8 +1853,6 @@ HGLRC context_create_wgl_attribs(const struct wined3d_gl_info
*gl_info, HDC hdc,
     ctx_attribs[ctx_attrib_idx++] = gl_info->selected_gl_version >> 16;
     ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MINOR_VERSION_ARB;
     ctx_attribs[ctx_attrib_idx++] = gl_info->selected_gl_version & 0xffff;
-    if (gl_info->selected_gl_version >= MAKEDWORD_VERSION(3, 2))
-        ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
     if (ctx_flags)
     {
         ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
@@ -1877,9 +1862,20 @@ HGLRC context_create_wgl_attribs(const struct wined3d_gl_info
*gl_info, HDC hdc,
     if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs)))
     {
-        if (ctx_flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+        if (gl_info->selected_gl_version >= MAKEDWORD_VERSION(3, 2))
         {
-            ctx_attribs[ctx_attrib_idx - 1] &=
~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+            if (ctx_flags)
+            {
+                ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+                ctx_attribs[ctx_attrib_idx - 1] = ctx_flags;
+            }
+            else
+            {
+                ctx_flags = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+                ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+                ctx_attribs[ctx_attrib_idx++] = ctx_flags;
+                ctx_attribs[ctx_attrib_idx] = 0;
+            }
             if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx,
ctx_attribs)))
                 WARN("Failed to create a WGL context with
wglCreateContextAttribsARB, last error %#x.\n",
                         GetLastError());
@@ -2176,15 +2172,6 @@ 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, 1);");
-    if (gl_info->supported[ARB_VERTEX_BLEND])
-    {
-        /* Direct3D always uses n-1 weights for n world matrices and uses
-         * 1 - sum for the last one this is equal to GL_WEIGHT_SUM_UNITY_ARB.
-         * Enabling it doesn't do anything unless GL_VERTEX_BLEND_ARB isn't
-         * enabled as well. */
-        gl_info->gl_ops.gl.p_glEnable(GL_WEIGHT_SUM_UNITY_ARB);
-        checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
-    }
     if (gl_info->supported[NV_TEXTURE_SHADER2])
     {
         /* Set up the previous texture input for all shader units. This applies to bump
mapping, and in d3d
@@ -2270,6 +2257,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain
*swapchain,
     if (device->dummy_textures.tex_2d)
         context_bind_dummy_textures(device, ret);
+    /* Initialise all rectangles to avoid resetting unused ones later. */
+    gl_info->gl_ops.gl.p_glScissor(0, 0, 0, 0);
+    checkGLcall("glScissor");
+
     TRACE("Created context %p.\n", ret);
     return ret;
@@ -2368,28 +2359,6 @@ const DWORD *context_get_tex_unit_mapping(const struct
wined3d_context *context,
     return context->tex_unit_map;
 }
-/* Context activation is done by the caller. */
-static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width, UINT
height)
-{
-    const GLdouble projection[] =
-    {
-        2.0 / width,          0.0,  0.0, 0.0,
-                0.0, 2.0 / height,  0.0, 0.0,
-                0.0,          0.0,  2.0, 0.0,
-               -1.0,         -1.0, -1.0, 1.0,
-    };
-
-    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
-    {
-        gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
-        checkGLcall("glMatrixMode(GL_PROJECTION)");
-        gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
-        checkGLcall("glLoadMatrixd");
-    }
-    gl_info->gl_ops.gl.p_glViewport(0, 0, width, height);
-    checkGLcall("glViewport");
-}
-
 static void context_get_rt_size(const struct wined3d_context *context, SIZE *size)
 {
     const struct wined3d_texture *rt = context->current_rt.texture;
@@ -2438,206 +2407,6 @@ void context_enable_clip_distances(struct wined3d_context
*context, unsigned int
     checkGLcall("toggle clip distances");
 }
-/*****************************************************************************
- * SetupForBlit
- *
- * Sets up a context for DirectDraw blitting.
- * All texture units are disabled, texture unit 0 is set as current unit
- * fog, lighting, blending, alpha test, z test, scissor test, culling disabled
- * color writing enabled for all channels
- * register combiners disabled, shaders disabled
- * world matrix is set to identity, texture matrix 0 too
- * projection matrix is setup for drawing screen coordinates
- *
- * Params:
- *  This: Device to activate the context for
- *  context: Context to setup
- *
- *****************************************************************************/
-/* Context activation is done by the caller. */
-static void SetupForBlit(const struct wined3d_device *device, struct wined3d_context
*context)
-{
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    DWORD sampler;
-    SIZE rt_size;
-    int i;
-
-    TRACE("Setting up context %p for blitting\n", context);
-
-    context_get_rt_size(context, &rt_size);
-
-    if (context->last_was_blit)
-    {
-        if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy)
-        {
-            set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
-            context->blit_w = rt_size.cx;
-            context->blit_h = rt_size.cy;
-            /* No need to dirtify here, the states are still dirtified because
-             * they weren't applied since the last SetupForBlit() call. */
-        }
-        TRACE("Context is already set up for blitting, nothing to do\n");
-        return;
-    }
-    context->last_was_blit = TRUE;
-
-    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
-    {
-        /* Disable all textures. The caller can then bind a texture it wants to blit
-         * from
-         *
-         * The blitting code uses (for now) the fixed function pipeline, so make sure to
reset all fixed
-         * function texture unit. No need to care for higher samplers
-         */
-        for (i = gl_info->limits.textures - 1; i > 0 ; --i)
-        {
-            sampler = context->rev_tex_unit_map[i];
-            context_active_texture(context, gl_info, i);
-
-            if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
-            {
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-                checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
-            }
-            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
-            checkGLcall("glDisable GL_TEXTURE_3D");
-            if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
-            {
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
-                checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
-            }
-            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
-            checkGLcall("glDisable GL_TEXTURE_2D");
-
-            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_REPLACE);
-            checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_REPLACE);");
-
-            if (sampler != WINED3D_UNMAPPED_STAGE)
-            {
-                if (sampler < MAX_TEXTURES)
-                    context_invalidate_state(context, STATE_TEXTURESTAGE(sampler,
WINED3D_TSS_COLOR_OP));
-                context_invalidate_state(context, STATE_SAMPLER(sampler));
-            }
-        }
-
-        context_active_texture(context, gl_info, 0);
-        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
-        {
-            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-            checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
-        }
-        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
-        checkGLcall("glDisable GL_TEXTURE_3D");
-        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
-        {
-            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
-            checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
-        }
-        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
-        checkGLcall("glDisable GL_TEXTURE_2D");
-
-        gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_REPLACE);
-
-        gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
-        checkGLcall("glMatrixMode(GL_TEXTURE)");
-        gl_info->gl_ops.gl.p_glLoadIdentity();
-        checkGLcall("glLoadIdentity()");
-
-        if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
-        {
-            gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
-                    GL_TEXTURE_LOD_BIAS_EXT, 0.0f);
-            checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ...");
-        }
-
-        /* Setup transforms */
-        gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
-        checkGLcall("glMatrixMode(GL_MODELVIEW)");
-        gl_info->gl_ops.gl.p_glLoadIdentity();
-        checkGLcall("glLoadIdentity()");
-        context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
-
-        /* Other misc states */
-        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
-        checkGLcall("glDisable(GL_ALPHA_TEST)");
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE));
-        gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
-        checkGLcall("glDisable GL_LIGHTING");
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING));
-        glDisableWINE(GL_FOG);
-        checkGLcall("glDisable GL_FOG");
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE));
-    }
-
-    if (gl_info->supported[ARB_SAMPLER_OBJECTS])
-        GL_EXTCALL(glBindSampler(0, 0));
-    context_active_texture(context, gl_info, 0);
-
-    sampler = context->rev_tex_unit_map[0];
-    if (sampler != WINED3D_UNMAPPED_STAGE)
-    {
-        if (sampler < MAX_TEXTURES)
-        {
-            context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 +
sampler));
-            context_invalidate_state(context, STATE_TEXTURESTAGE(sampler,
WINED3D_TSS_COLOR_OP));
-        }
-        context_invalidate_state(context, STATE_SAMPLER(sampler));
-    }
-
-    /* Other misc states */
-    gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
-    checkGLcall("glDisable GL_DEPTH_TEST");
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE));
-    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
-    checkGLcall("glDisable GL_BLEND");
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
-    gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
-    checkGLcall("glDisable GL_CULL_FACE");
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE));
-    gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
-    checkGLcall("glDisable GL_STENCIL_TEST");
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE));
-    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
-    checkGLcall("glDisable GL_SCISSOR_TEST");
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
-    if (gl_info->supported[ARB_POINT_SPRITE])
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
-        checkGLcall("glDisable GL_POINT_SPRITE_ARB");
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE));
-    }
-    gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE);
-    checkGLcall("glColorMask");
-    for (i = 0; i < MAX_RENDER_TARGETS; ++i)
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITE(i)));
-    if (gl_info->supported[EXT_SECONDARY_COLOR])
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
-        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
-        checkGLcall("glDisable(GL_COLOR_SUM_EXT)");
-    }
-
-    context->last_was_rhw = TRUE;
-    context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */
-
-    context_enable_clip_distances(context, 0);
-    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
-
-    /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */
-    if (gl_info->supported[ARB_CLIP_CONTROL])
-        GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE));
-
-    set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
-
-    /* Disable shaders */
-    device->shader_backend->shader_disable(device->shader_priv, context);
-
-    context->blit_w = rt_size.cx;
-    context->blit_h = rt_size.cy;
-    context_invalidate_state(context, STATE_VIEWPORT);
-    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
-}
-
 static inline BOOL is_rt_mask_onscreen(DWORD rt_mask)
 {
     return rt_mask & (1u << 31);
@@ -2756,11 +2525,9 @@ void context_bind_texture(struct wined3d_context *context, GLenum
target, GLuint
                 break;
             case GL_TEXTURE_1D:
                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D,
textures->tex_1d);
-                checkGLcall("glBindTexture");
                 break;
             case GL_TEXTURE_1D_ARRAY:
                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY,
textures->tex_1d_array);
-                checkGLcall("glBindTexture");
                 break;
             case GL_TEXTURE_2D:
                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D,
textures->tex_2d);
@@ -2900,7 +2667,7 @@ static void context_set_render_offscreen(struct wined3d_context
*context, BOOL o
     context_invalidate_state(context, STATE_SCISSORRECT);
     if (!context->gl_info->supported[ARB_CLIP_CONTROL])
     {
-        context_invalidate_state(context, STATE_FRONTFACE);
+        context_invalidate_state(context, STATE_RASTERIZER);
         context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN);
         context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
     }
@@ -2967,12 +2734,12 @@ GLenum context_get_offscreen_gl_buffer(const struct
wined3d_context *context)
     }
 }
-static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context,
struct wined3d_texture *rt)
+static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context,
struct wined3d_resource *rt)
 {
-    if (!rt || rt->resource.format->id == WINED3DFMT_NULL)
+    if (!rt || rt->format->id == WINED3DFMT_NULL)
         return 0;
-    else if (rt->swapchain)
-        return context_generate_rt_mask_from_resource(&rt->resource);
+    else if (rt->type != WINED3D_RTYPE_BUFFER &&
texture_from_resource(rt)->swapchain)
+        return context_generate_rt_mask_from_resource(rt);
     else
         return context_generate_rt_mask(context_get_offscreen_gl_buffer(context));
 }
@@ -2980,9 +2747,13 @@ static DWORD context_generate_rt_mask_no_fbo(const struct
wined3d_context *conte
 /* Context activation is done by the caller. */
 void context_apply_blit_state(struct wined3d_context *context, const struct
wined3d_device *device)
 {
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_texture *rt = context->current_rt.texture;
-    struct wined3d_surface *surface;
     DWORD rt_mask, *cur_mask;
+    unsigned int i, sampler;
+    SIZE rt_size;
+
+    TRACE("Setting up context %p for blitting.\n", context);
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
@@ -2990,8 +2761,8 @@ void context_apply_blit_state(struct wined3d_context *context, const
struct wine
         {
             wined3d_texture_load(rt, context, FALSE);
-            surface =
rt->sub_resources[context->current_rt.sub_resource_idx].u.surface;
-            context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, surface, NULL,
rt->resource.draw_binding);
+            context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, &rt->resource,
+                    context->current_rt.sub_resource_idx, NULL, 0,
rt->resource.draw_binding);
             if (rt->resource.format->id != WINED3DFMT_NULL)
                 rt_mask = 1;
             else
@@ -3006,7 +2777,7 @@ void context_apply_blit_state(struct wined3d_context *context, const
struct wine
     }
     else
     {
-        rt_mask = context_generate_rt_mask_no_fbo(context, rt);
+        rt_mask = context_generate_rt_mask_no_fbo(context, &rt->resource);
     }
     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask :
&context->draw_buffers_mask;
@@ -3021,76 +2792,270 @@ void context_apply_blit_state(struct wined3d_context *context,
const struct wine
     {
         context_check_fbo_status(context, GL_FRAMEBUFFER);
     }
-
-    SetupForBlit(device, context);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
-}
-
-static BOOL have_framebuffer_attachment(unsigned int rt_count, struct
wined3d_rendertarget_view * const *rts,
-        const struct wined3d_rendertarget_view *ds)
-{
-    unsigned int i;
-    if (ds)
-        return TRUE;
+    context_get_rt_size(context, &rt_size);
-    for (i = 0; i < rt_count; ++i)
+    if (context->last_was_blit)
     {
-        if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
-            return TRUE;
+        if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy)
+        {
+            gl_info->gl_ops.gl.p_glViewport(0, 0, rt_size.cx, rt_size.cy);
+            context->viewport_count = WINED3D_MAX_VIEWPORTS;
+            context->blit_w = rt_size.cx;
+            context->blit_h = rt_size.cy;
+            /* No need to dirtify here, the states are still dirtified because
+             * they weren't applied since the last context_apply_blit_state()
+             * call. */
+        }
+        checkGLcall("blit state application");
+        TRACE("Context is already set up for blitting, nothing to do.\n");
+        return;
     }
+    context->last_was_blit = TRUE;
-    return FALSE;
-}
-
-/* Context activation is done by the caller. */
-BOOL context_apply_clear_state(struct wined3d_context *context, const struct
wined3d_state *state,
-        UINT rt_count, const struct wined3d_fb_state *fb)
-{
-    struct wined3d_rendertarget_view * const *rts = fb->render_targets;
-    struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    DWORD rt_mask = 0, *cur_mask;
-    unsigned int i;
+    if (gl_info->supported[ARB_SAMPLER_OBJECTS])
+        GL_EXTCALL(glBindSampler(0, 0));
+    context_active_texture(context, gl_info, 0);
-    if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb
-            || rt_count != gl_info->limits.buffers)
+    sampler = context->rev_tex_unit_map[0];
+    if (sampler != WINED3D_UNMAPPED_STAGE)
     {
-        if (!have_framebuffer_attachment(rt_count, rts, dsv))
+        if (sampler < MAX_TEXTURES)
         {
-            WARN("Invalid render target config, need at least one
attachment.\n");
-            return FALSE;
+            context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 +
sampler));
+            context_invalidate_state(context, STATE_TEXTURESTAGE(sampler,
WINED3D_TSS_COLOR_OP));
         }
+        context_invalidate_state(context, STATE_SAMPLER(sampler));
+    }
-        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
-        {
-            context_validate_onscreen_formats(context, dsv);
-
-            if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))
-            {
-                memset(context->blit_targets, 0, sizeof(context->blit_targets));
-                for (i = 0; i < rt_count; ++i)
-                {
-                    if (rts[i])
-                    {
-                        context->blit_targets[i].gl_view = rts[i]->gl_view;
-                        context->blit_targets[i].resource = rts[i]->resource;
-                        context->blit_targets[i].sub_resource_idx =
rts[i]->sub_resource_idx;
-                        context->blit_targets[i].layer_count = rts[i]->layer_count;
-                    }
-                    if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
-                        rt_mask |= (1u << i);
-                }
-                context_apply_fbo_state(context, GL_FRAMEBUFFER,
context->blit_targets,
-                        wined3d_rendertarget_view_get_surface(dsv),
-                        rt_count ? rts[0]->resource->draw_binding : 0,
-                        dsv ? dsv->resource->draw_binding : 0);
-            }
-            else
-            {
-                context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL,
-                        WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE);
-                rt_mask = context_generate_rt_mask_from_resource(rts[0]->resource);
+    if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE));
+    }
+    gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE));
+    gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+    if (gl_info->supported[ARB_POINT_SPRITE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE));
+    }
+    if (gl_info->supported[ARB_FRAMEBUFFER_SRGB])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
+    }
+    gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    for (i = 0; i < MAX_RENDER_TARGETS; ++i)
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITE(i)));
+
+    context->last_was_rhw = TRUE;
+    context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */
+
+    context_enable_clip_distances(context, 0);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
+
+    /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */
+    if (gl_info->supported[ARB_CLIP_CONTROL])
+        GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE));
+    gl_info->gl_ops.gl.p_glViewport(0, 0, rt_size.cx, rt_size.cy);
+    context->viewport_count = WINED3D_MAX_VIEWPORTS;
+    context_invalidate_state(context, STATE_VIEWPORT);
+
+    device->shader_backend->shader_disable(device->shader_priv, context);
+
+    context->blit_w = rt_size.cx;
+    context->blit_h = rt_size.cy;
+
+    checkGLcall("blit state application");
+}
+
+static void context_apply_blit_projection(const struct wined3d_context *context, unsigned
int w, unsigned int h)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const GLdouble projection[] =
+    {
+        2.0 / w,     0.0,  0.0, 0.0,
+            0.0, 2.0 / h,  0.0, 0.0,
+            0.0,     0.0,  2.0, 0.0,
+           -1.0,    -1.0, -1.0, 1.0,
+    };
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+    gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
+}
+
+/* Setup OpenGL states for fixed-function blitting. */
+/* Context activation is done by the caller. */
+void context_apply_ffp_blit_state(struct wined3d_context *context, const struct
wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int i, sampler;
+
+    if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+        ERR("Applying fixed-function state without legacy context support.\n");
+
+    if (context->last_was_ffp_blit)
+    {
+        SIZE rt_size;
+
+        context_get_rt_size(context, &rt_size);
+        if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy)
+            context_apply_blit_projection(context, rt_size.cx, rt_size.cy);
+        context_apply_blit_state(context, device);
+
+        checkGLcall("ffp blit state application");
+        return;
+    }
+    context->last_was_ffp_blit = TRUE;
+
+    context_apply_blit_state(context, device);
+
+    /* Disable all textures. The caller can then bind a texture it wants to blit
+     * from. */
+    for (i = gl_info->limits.textures - 1; i > 0 ; --i)
+    {
+        context_active_texture(context, gl_info, i);
+
+        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+
+        gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
GL_REPLACE);
+
+        sampler = context->rev_tex_unit_map[i];
+        if (sampler != WINED3D_UNMAPPED_STAGE)
+        {
+            if (sampler < MAX_TEXTURES)
+                context_invalidate_state(context, STATE_TEXTURESTAGE(sampler,
WINED3D_TSS_COLOR_OP));
+            context_invalidate_state(context, STATE_SAMPLER(sampler));
+        }
+    }
+
+    context_active_texture(context, gl_info, 0);
+
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+
+    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
+        gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
GL_TEXTURE_LOD_BIAS_EXT, 0.0f);
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+
+    /* Setup transforms. */
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
+    context_apply_blit_projection(context, context->blit_w, context->blit_h);
+    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+
+    /* Other misc states. */
+    gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING));
+    glDisableWINE(GL_FOG);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE));
+
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
+    }
+    checkGLcall("ffp blit state application");
+}
+
+static BOOL have_framebuffer_attachment(unsigned int rt_count, struct
wined3d_rendertarget_view * const *rts,
+        const struct wined3d_rendertarget_view *ds)
+{
+    unsigned int i;
+
+    if (ds)
+        return TRUE;
+
+    for (i = 0; i < rt_count; ++i)
+    {
+        if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* Context activation is done by the caller. */
+BOOL context_apply_clear_state(struct wined3d_context *context, const struct
wined3d_state *state,
+        UINT rt_count, const struct wined3d_fb_state *fb)
+{
+    struct wined3d_rendertarget_view * const *rts = fb->render_targets;
+    struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD rt_mask = 0, *cur_mask;
+    unsigned int i;
+
+    if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb
+            || rt_count != gl_info->limits.buffers)
+    {
+        if (!have_framebuffer_attachment(rt_count, rts, dsv))
+        {
+            WARN("Invalid render target config, need at least one
attachment.\n");
+            return FALSE;
+        }
+
+        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        {
+            struct wined3d_rendertarget_info ds_info = {{0}};
+
+            context_validate_onscreen_formats(context, dsv);
+
+            if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))
+            {
+                memset(context->blit_targets, 0, sizeof(context->blit_targets));
+                for (i = 0; i < rt_count; ++i)
+                {
+                    if (rts[i])
+                    {
+                        context->blit_targets[i].gl_view = rts[i]->gl_view;
+                        context->blit_targets[i].resource = rts[i]->resource;
+                        context->blit_targets[i].sub_resource_idx =
rts[i]->sub_resource_idx;
+                        context->blit_targets[i].layer_count = rts[i]->layer_count;
+                    }
+                    if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
+                        rt_mask |= (1u << i);
+                }
+
+                if (dsv)
+                {
+                    ds_info.gl_view = dsv->gl_view;
+                    ds_info.resource = dsv->resource;
+                    ds_info.sub_resource_idx = dsv->sub_resource_idx;
+                    ds_info.layer_count = dsv->layer_count;
+                }
+
+                context_apply_fbo_state(context, GL_FRAMEBUFFER,
context->blit_targets, &ds_info,
+                        rt_count ? rts[0]->resource->draw_binding : 0,
+                        dsv ? dsv->resource->draw_binding : 0);
+            }
+            else
+            {
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, &ds_info,
+                        WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE);
+                rt_mask = context_generate_rt_mask_from_resource(rts[0]->resource);
             }
             /* If the framebuffer is not the device's fb the device's fb has to
be reapplied
@@ -3100,8 +3065,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context,
const struct win
         }
         else
         {
-            rt_mask = context_generate_rt_mask_no_fbo(context,
-                    rt_count ?
wined3d_rendertarget_view_get_surface(rts[0])->container : NULL);
+            rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ?
rts[0]->resource : NULL);
         }
     }
     else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
@@ -3115,8 +3079,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context,
const struct win
     }
     else
     {
-        rt_mask = context_generate_rt_mask_no_fbo(context,
-                rt_count ? wined3d_rendertarget_view_get_surface(rts[0])->container :
NULL);
+        rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ? rts[0]->resource
: NULL);
     }
     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask :
&context->draw_buffers_mask;
@@ -3134,6 +3097,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context,
const struct win
     }
     context->last_was_blit = FALSE;
+    context->last_was_ffp_blit = FALSE;
     /* Blending and clearing should be orthogonal, but tests on the nvidia
      * driver show that disabling blending when clearing improves the clearing
@@ -3165,7 +3129,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context
*context, const
     unsigned int i;
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
-        return context_generate_rt_mask_no_fbo(context,
wined3d_rendertarget_view_get_surface(rts[0])->container);
+        return context_generate_rt_mask_no_fbo(context, rts[0]->resource);
     else if (!context->render_offscreen)
         return context_generate_rt_mask_from_resource(rts[0]->resource);
@@ -3202,9 +3166,11 @@ void context_state_fb(struct wined3d_context *context, const struct
wined3d_stat
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
+        struct wined3d_rendertarget_info ds_info = {{0}};
+
         if (!context->render_offscreen)
         {
-            context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL,
+            context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, &ds_info,
                     WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE);
         }
         else
@@ -3225,8 +3191,16 @@ void context_state_fb(struct wined3d_context *context, const struct
wined3d_stat
                 if (!color_location)
                     color_location =
fb->render_targets[i]->resource->draw_binding;
             }
-            context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets,
-                    wined3d_rendertarget_view_get_surface(fb->depth_stencil),
+
+            if (fb->depth_stencil)
+            {
+                ds_info.gl_view = fb->depth_stencil->gl_view;
+                ds_info.resource = fb->depth_stencil->resource;
+                ds_info.sub_resource_idx = fb->depth_stencil->sub_resource_idx;
+                ds_info.layer_count = fb->depth_stencil->layer_count;
+            }
+
+            context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets,
&ds_info,
                     color_location, fb->depth_stencil ?
fb->depth_stencil->resource->draw_binding : 0);
         }
     }
@@ -4053,6 +4027,7 @@ static BOOL context_apply_draw_state(struct wined3d_context
*context,
     context->numDirtyEntries = 0; /* This makes the whole list clean */
     context->last_was_blit = FALSE;
+    context->last_was_ffp_blit = FALSE;
     return TRUE;
 }
@@ -4114,6 +4089,7 @@ static void context_apply_compute_state(struct wined3d_context
*context,
     context_invalidate_state(context, STATE_FRAMEBUFFER);
     context->last_was_blit = FALSE;
+    context->last_was_ffp_blit = FALSE;
 }
 static BOOL use_transform_feedback(const struct wined3d_state *state)
@@ -4377,9 +4353,6 @@ void dispatch_compute(struct wined3d_device *device, const struct
wined3d_state
     GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS));
     checkGLcall("glMemoryBarrier");
-    if (wined3d_settings.strict_draw_ordering)
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts.
*/
-
     context_release(context);
 }
@@ -4565,6 +4538,7 @@ static const BYTE *software_vertex_blending(struct wined3d_context
*context,
         case WINED3D_FFP_EMIT_FLOAT4: vector[3] = data[3];
         case WINED3D_FFP_EMIT_FLOAT3: vector[2] = data[2];
         case WINED3D_FFP_EMIT_FLOAT2: vector[1] = data[1];
+        case WINED3D_FFP_EMIT_FLOAT1: vector[0] = data[0]; break;
         default:
             FIXME("unsupported value format: %u\n", SI_FORMAT(element_idx));
             return (BYTE *)data;
@@ -5052,13 +5026,12 @@ void draw_primitive(struct wined3d_device *device, const struct
wined3d_state *s
                 WARN_(d3d_perf)("Using software emulation because manual fog
coordinates are provided.\n");
             emulation = TRUE;
         }
-         else if (use_indexed_vertex_blending(state, stream_info) &&
use_software_vertex_processing(context->device))
+        else if (use_indexed_vertex_blending(state, stream_info) &&
use_software_vertex_processing(context->device))
         {
             WARN_(d3d_perf)("Using software emulation because application requested
SVP.\n");
             emulation = TRUE;
         }
-
         if (emulation)
         {
             si_emulated = context->stream_info;
@@ -5086,7 +5059,9 @@ void draw_primitive(struct wined3d_device *device, const struct
wined3d_state *s
         }
         else if (!context->transform_feedback_active)
         {
-            GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type);
+            enum wined3d_primitive_type primitive_type = shader->u.gs.output_type
+                    ? shader->u.gs.output_type :
d3d_primitive_type_from_gl(state->gl_primitive_type);
+            GLenum mode = gl_tfb_primitive_type_from_d3d(primitive_type);
             GL_EXTCALL(glBeginTransformFeedback(mode));
             checkGLcall("glBeginTransformFeedback");
             context->transform_feedback_active = 1;
@@ -5141,8 +5116,663 @@ void draw_primitive(struct wined3d_device *device, const struct
wined3d_state *s
     for (i = 0; i < context->buffer_fence_count; ++i)
         wined3d_fence_issue(context->buffer_fences[i], device);
-    if (wined3d_settings.strict_draw_ordering)
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts.
*/
-
     context_release(context);
 }
+
+void context_unload_tex_coords(const struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int texture_idx;
+
+    for (texture_idx = 0; texture_idx < gl_info->limits.texture_coords;
++texture_idx)
+    {
+        gl_info->gl_ops.ext.p_glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx);
+        gl_info->gl_ops.gl.p_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+}
+
+void context_load_tex_coords(const struct wined3d_context *context, const struct
wined3d_stream_info *si,
+        GLuint *current_bo, const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int mapped_stage = 0;
+    unsigned int texture_idx;
+
+    for (texture_idx = 0; texture_idx <
context->d3d_info->limits.ffp_blend_stages; ++texture_idx)
+    {
+        unsigned int coord_idx =
state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX];
+
+        if ((mapped_stage = context->tex_unit_map[texture_idx]) ==
WINED3D_UNMAPPED_STAGE)
+            continue;
+
+        if (mapped_stage >= gl_info->limits.texture_coords)
+        {
+            FIXME("Attempted to load unsupported texture coordinate %u.\n",
mapped_stage);
+            continue;
+        }
+
+        if (coord_idx < MAX_TEXTURES && (si->use_map & (1u <<
(WINED3D_FFP_TEXCOORD0 + coord_idx))))
+        {
+            const struct wined3d_stream_info_element *e =
&si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx];
+
+            TRACE("Setting up texture %u, idx %d, coord_idx %u, data
{%#x:%p}.\n",
+                    texture_idx, mapped_stage, coord_idx, e->data.buffer_object,
e->data.addr);
+
+            if (*current_bo != e->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
+                checkGLcall("glBindBuffer");
+                *current_bo = e->data.buffer_object;
+            }
+
+            GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
+            checkGLcall("glClientActiveTextureARB");
+
+            /* The coords to supply depend completely on the fvf/vertex shader. */
+            gl_info->gl_ops.gl.p_glTexCoordPointer(e->format->gl_vtx_format,
e->format->gl_vtx_type, e->stride,
+                    e->data.addr + state->load_base_vertex_index * e->stride);
+            gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        }
+        else
+        {
+            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
+        }
+    }
+    if (gl_info->supported[NV_REGISTER_COMBINERS])
+    {
+        /* The number of the mapped stages increases monotonically, so it's fine to
use the last used one. */
+        for (texture_idx = mapped_stage + 1; texture_idx <
gl_info->limits.textures; ++texture_idx)
+        {
+            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
+        }
+    }
+
+    checkGLcall("loadTexCoords");
+}
+
+/* This should match any arrays loaded in context_load_vertex_data(). */
+static void context_unload_vertex_data(struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (!context->namedArraysLoaded)
+        return;
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_VERTEX_ARRAY);
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_NORMAL_ARRAY);
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_COLOR_ARRAY);
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+        gl_info->gl_ops.gl.p_glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+    context_unload_tex_coords(context);
+    context->namedArraysLoaded = FALSE;
+}
+
+static void context_load_vertex_data(struct wined3d_context *context,
+        const struct wined3d_stream_info *si, const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_stream_info_element *e;
+    GLuint current_bo;
+
+    TRACE("context %p, si %p, state %p.\n", context, si, state);
+
+    /* This is used for the fixed-function pipeline only, and the
+     * fixed-function pipeline doesn't do instancing. */
+    context->instance_count = 0;
+    current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0;
+
+    /* Blend data */
+    if ((si->use_map & (1u << WINED3D_FFP_BLENDWEIGHT))
+            || si->use_map & (1u << WINED3D_FFP_BLENDINDICES))
+    {
+        /* TODO: Support vertex blending in immediate mode draws. No need to
+         * write a FIXME here, this is done after the general vertex
+         * declaration decoding. */
+        WARN("Vertex blending not supported.\n");
+    }
+
+    /* Point Size */
+    if (si->use_map & (1u << WINED3D_FFP_PSIZE))
+    {
+        /* No such functionality in the fixed-function GL pipeline. */
+        WARN("Per-vertex point size not supported.\n");
+    }
+
+    /* Position */
+    if (si->use_map & (1u << WINED3D_FFP_POSITION))
+    {
+        e = &si->elements[WINED3D_FFP_POSITION];
+
+        if (current_bo != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
+            checkGLcall("glBindBuffer");
+            current_bo = e->data.buffer_object;
+        }
+
+        TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n",
+                e->format->gl_vtx_format, e->format->gl_vtx_type,
e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glVertexPointer(e->format->gl_vtx_format,
e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glVertexPointer(...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
+    }
+
+    /* Normals */
+    if (si->use_map & (1u << WINED3D_FFP_NORMAL))
+    {
+        e = &si->elements[WINED3D_FFP_NORMAL];
+
+        if (current_bo != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
+            checkGLcall("glBindBuffer");
+            current_bo = e->data.buffer_object;
+        }
+
+        TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type,
e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glNormalPointer(e->format->gl_vtx_type,
e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glNormalPointer(...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
+
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0);
+        checkGLcall("glNormal3f(0, 0, 0)");
+    }
+
+    /* Diffuse colour */
+    if (si->use_map & (1u << WINED3D_FFP_DIFFUSE))
+    {
+        e = &si->elements[WINED3D_FFP_DIFFUSE];
+
+        if (current_bo != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
+            checkGLcall("glBindBuffer");
+            current_bo = e->data.buffer_object;
+        }
+
+        TRACE("glColorPointer(%#x, %#x %#x, %p);\n",
+                e->format->gl_vtx_format, e->format->gl_vtx_type,
e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glColorPointer(e->format->gl_vtx_format,
e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
+
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        checkGLcall("glColor4f(1, 1, 1, 1)");
+    }
+
+    /* Specular colour */
+    if (si->use_map & (1u << WINED3D_FFP_SPECULAR))
+    {
+        TRACE("Setting specular colour.\n");
+
+        e = &si->elements[WINED3D_FFP_SPECULAR];
+
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+        {
+            GLenum type = e->format->gl_vtx_type;
+            GLint format = e->format->gl_vtx_format;
+
+            if (current_bo != e->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
+                checkGLcall("glBindBuffer");
+                current_bo = e->data.buffer_object;
+            }
+
+            if (format != 4 || (gl_info->quirks &
WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
+            {
+                /* Usually specular colors only allow 3 components, since they have no
alpha. In D3D, the specular alpha
+                 * contains the fog coordinate, which is passed to GL with
GL_EXT_fog_coord. However, the fixed function
+                 * vertex pipeline can pass the specular alpha through, and pixel shaders
can read it. So it GL accepts
+                 * 4 component secondary colors use it
+                 */
+                TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format,
type, e->stride,
+                        e->data.addr + state->load_base_vertex_index *
e->stride);
+                GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride,
+                        e->data.addr + state->load_base_vertex_index *
e->stride));
+                checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
+            }
+            else
+            {
+                switch (type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                        TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x,
%p);\n", e->stride,
+                                e->data.addr + state->load_base_vertex_index *
e->stride);
+                        GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE,
e->stride,
+                                e->data.addr + state->load_base_vertex_index *
e->stride));
+                        checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE,
...)");
+                        break;
+
+                    default:
+                        FIXME("Add 4 component specular colour pointers for type
%#x.\n", type);
+                        /* Make sure that the right colour component is dropped. */
+                        TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n",
type, e->stride,
+                                e->data.addr + state->load_base_vertex_index *
e->stride);
+                        GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride,
+                                e->data.addr + state->load_base_vertex_index *
e->stride));
+                        checkGLcall("glSecondaryColorPointerEXT(3, type,
...)");
+                }
+            }
+            gl_info->gl_ops.gl.p_glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+        }
+        else
+        {
+            WARN("Specular colour is not supported in this GL
implementation.\n");
+        }
+    }
+    else
+    {
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+        {
+            GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
+            checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
+        }
+        else
+        {
+            WARN("Specular colour is not supported in this GL
implementation.\n");
+        }
+    }
+
+    /* Texture coordinates */
+    context_load_tex_coords(context, si, ¤t_bo, state);
+}
+
+static void context_unload_numbered_array(struct wined3d_context *context, unsigned int
i)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glDisableVertexAttribArray(i));
+    checkGLcall("glDisableVertexAttribArray");
+    if (gl_info->supported[ARB_INSTANCED_ARRAYS])
+        GL_EXTCALL(glVertexAttribDivisor(i, 0));
+
+    context->numbered_array_mask &= ~(1u << i);
+}
+
+static void context_unload_numbered_arrays(struct wined3d_context *context)
+{
+    unsigned int i;
+
+    while (context->numbered_array_mask)
+    {
+        i = wined3d_bit_scan(&context->numbered_array_mask);
+        context_unload_numbered_array(context, i);
+    }
+}
+
+static void context_load_numbered_arrays(struct wined3d_context *context,
+        const struct wined3d_stream_info *stream_info, const struct wined3d_state *state)
+{
+    const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLuint current_bo;
+    unsigned int i;
+
+    /* Default to no instancing. */
+    context->instance_count = 0;
+    current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0;
+
+    for (i = 0; i < MAX_ATTRIBS; ++i)
+    {
+        const struct wined3d_stream_info_element *element =
&stream_info->elements[i];
+        const struct wined3d_stream_state *stream;
+
+        if (!(stream_info->use_map & (1u << i)))
+        {
+            if (context->numbered_array_mask & (1u << i))
+                context_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));
+            else
+                GL_EXTCALL(glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f));
+            continue;
+        }
+
+        stream = &state->streams[element->stream_idx];
+
+        if ((stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) &&
!context->instance_count)
+            context->instance_count = state->streams[0].frequency ?
state->streams[0].frequency : 1;
+
+        if (gl_info->supported[ARB_INSTANCED_ARRAYS])
+        {
+            GL_EXTCALL(glVertexAttribDivisor(i, element->divisor));
+        }
+        else if (element->divisor)
+        {
+            /* Unload instanced arrays, they will be loaded using immediate
+             * mode instead. */
+            if (context->numbered_array_mask & (1u << i))
+                context_unload_numbered_array(context, i);
+            continue;
+        }
+
+        TRACE("Loading array %u [VBO=%u].\n", i,
element->data.buffer_object);
+
+        if (element->stride)
+        {
+            if (current_bo != element->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER,
element->data.buffer_object));
+                checkGLcall("glBindBuffer");
+                current_bo = element->data.buffer_object;
+            }
+            /* Use the VBO to find out if a vertex buffer exists, not the vb
+             * pointer. vb can point to a user pointer data blob. In that case
+             * current_bo will be 0. If there is a vertex buffer but no vbo we
+             * won't be load converted attributes anyway. */
+            if (vs && vs->reg_maps.shader_version.major >= 4
+                    && (element->format->flags[WINED3D_GL_RES_TYPE_BUFFER]
& WINED3DFMT_FLAG_INTEGER))
+            {
+                GL_EXTCALL(glVertexAttribIPointer(i,
element->format->gl_vtx_format, element->format->gl_vtx_type,
+                        element->stride, element->data.addr +
state->load_base_vertex_index * element->stride));
+            }
+            else
+            {
+                GL_EXTCALL(glVertexAttribPointer(i, element->format->gl_vtx_format,
element->format->gl_vtx_type,
+                        element->format->gl_normalized, element->stride,
+                        element->data.addr + state->load_base_vertex_index *
element->stride));
+            }
+
+            if (!(context->numbered_array_mask & (1u << i)))
+            {
+                GL_EXTCALL(glEnableVertexAttribArray(i));
+                context->numbered_array_mask |= (1u << i);
+            }
+        }
+        else
+        {
+            /* Stride = 0 means always the same values.
+             * glVertexAttribPointer() doesn't do that. Instead disable the
+             * pointer and set up the attribute statically. But we have to
+             * figure out the system memory address. */
+            const BYTE *ptr = element->data.addr;
+            if (element->data.buffer_object)
+                ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(stream->buffer, context);
+
+            if (context->numbered_array_mask & (1u << i))
+                context_unload_numbered_array(context, i);
+
+            switch (element->format->id)
+            {
+                case WINED3DFMT_R32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib1fv(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib2fv(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32B32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib3fv(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib4fv(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R8G8B8A8_UINT:
+                    GL_EXTCALL(glVertexAttrib4ubv(i, ptr));
+                    break;
+                case WINED3DFMT_B8G8R8A8_UNORM:
+                    if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
+                    {
+                        const DWORD *src = (const DWORD *)ptr;
+                        DWORD c = *src & 0xff00ff00u;
+                        c |= (*src & 0xff0000u) >> 16;
+                        c |= (*src & 0xffu) << 16;
+                        GL_EXTCALL(glVertexAttrib4Nubv(i, (GLubyte *)&c));
+                        break;
+                    }
+                    /* else fallthrough */
+                case WINED3DFMT_R8G8B8A8_UNORM:
+                    GL_EXTCALL(glVertexAttrib4Nubv(i, ptr));
+                    break;
+                case WINED3DFMT_R16G16_SINT:
+                    GL_EXTCALL(glVertexAttrib2sv(i, (const GLshort *)ptr));
+                    break;
+                case WINED3DFMT_R16G16B16A16_SINT:
+                    GL_EXTCALL(glVertexAttrib4sv(i, (const GLshort *)ptr));
+                    break;
+                case WINED3DFMT_R16G16_SNORM:
+                {
+                    const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort
*)ptr)[1], 0, 1};
+                    GL_EXTCALL(glVertexAttrib4Nsv(i, s));
+                    break;
+                }
+                case WINED3DFMT_R16G16_UNORM:
+                {
+                    const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort
*)ptr)[1], 0, 1};
+                    GL_EXTCALL(glVertexAttrib4Nusv(i, s));
+                    break;
+                }
+                case WINED3DFMT_R16G16B16A16_SNORM:
+                    GL_EXTCALL(glVertexAttrib4Nsv(i, (const GLshort *)ptr));
+                    break;
+                case WINED3DFMT_R16G16B16A16_UNORM:
+                    GL_EXTCALL(glVertexAttrib4Nusv(i, (const GLushort *)ptr));
+                    break;
+                case WINED3DFMT_R10G10B10X2_UINT:
+                    FIXME("Unsure about WINED3DDECLTYPE_UDEC3.\n");
+                    /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
+                    break;
+                case WINED3DFMT_R10G10B10X2_SNORM:
+                    FIXME("Unsure about WINED3DDECLTYPE_DEC3N.\n");
+                    /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
+                    break;
+                case WINED3DFMT_R16G16_FLOAT:
+                    if (gl_info->supported[NV_HALF_FLOAT] &&
gl_info->supported[NV_VERTEX_PROGRAM])
+                    {
+                        /* Not supported by GL_ARB_half_float_vertex. */
+                        GL_EXTCALL(glVertexAttrib2hvNV(i, (const GLhalfNV *)ptr));
+                    }
+                    else
+                    {
+                        float x = float_16_to_32(((const unsigned short *)ptr) + 0);
+                        float y = float_16_to_32(((const unsigned short *)ptr) + 1);
+                        GL_EXTCALL(glVertexAttrib2f(i, x, y));
+                    }
+                    break;
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    if (gl_info->supported[NV_HALF_FLOAT] &&
gl_info->supported[NV_VERTEX_PROGRAM])
+                    {
+                        /* Not supported by GL_ARB_half_float_vertex. */
+                        GL_EXTCALL(glVertexAttrib4hvNV(i, (const GLhalfNV *)ptr));
+                    }
+                    else
+                    {
+                        float x = float_16_to_32(((const unsigned short *)ptr) + 0);
+                        float y = float_16_to_32(((const unsigned short *)ptr) + 1);
+                        float z = float_16_to_32(((const unsigned short *)ptr) + 2);
+                        float w = float_16_to_32(((const unsigned short *)ptr) + 3);
+                        GL_EXTCALL(glVertexAttrib4f(i, x, y, z, w));
+                    }
+                    break;
+                default:
+                    ERR("Unexpected declaration in stride 0 attributes.\n");
+                    break;
+
+            }
+        }
+    }
+    checkGLcall("Loading numbered arrays");
+}
+
+void context_update_stream_sources(struct wined3d_context *context, const struct
wined3d_state *state)
+{
+
+    if (context->use_immediate_mode_draw)
+        return;
+
+    context_unload_vertex_data(context);
+    if (context->d3d_info->ffp_generic_attributes || use_vs(state))
+    {
+        TRACE("Loading numbered arrays.\n");
+        context_load_numbered_arrays(context, &context->stream_info, state);
+        return;
+    }
+
+    TRACE("Loading named arrays.\n");
+    context_unload_numbered_arrays(context);
+    context_load_vertex_data(context, &context->stream_info, state);
+    context->namedArraysLoaded = TRUE;
+}
+
+static void apply_texture_blit_state(const struct wined3d_gl_info *gl_info, struct
gl_texture *texture,
+        GLenum target, unsigned int level, enum wined3d_texture_filter_type filter)
+{
+    gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
wined3d_gl_mag_filter(filter));
+    gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+            wined3d_gl_min_mip_filter(filter, WINED3D_TEXF_NONE));
+    gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+        gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
GL_SKIP_DECODE_EXT);
+    gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, level);
+
+    /* We changed the filtering settings on the texture. Make sure they get
+     * reset on subsequent draws. */
+    texture->sampler_desc.mag_filter = WINED3D_TEXF_POINT;
+    texture->sampler_desc.min_filter = WINED3D_TEXF_POINT;
+    texture->sampler_desc.mip_filter = WINED3D_TEXF_NONE;
+    texture->sampler_desc.address_u = WINED3D_TADDRESS_CLAMP;
+    texture->sampler_desc.address_v = WINED3D_TADDRESS_CLAMP;
+    texture->sampler_desc.srgb_decode = FALSE;
+    texture->base_level = level;
+}
+
+/* Context activation is done by the caller. */
+void context_draw_shaded_quad(struct wined3d_context *context, struct wined3d_texture
*texture,
+        unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect,
+        enum wined3d_texture_filter_type filter)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_blt_info info;
+    unsigned int level, w, h, i;
+    SIZE dst_size;
+    struct blit_vertex
+    {
+        float x, y;
+        struct wined3d_vec3 texcoord;
+    }
+    quad[4];
+
+    texture2d_get_blt_info(texture, sub_resource_idx, src_rect, &info);
+
+    level = sub_resource_idx % texture->level_count;
+    context_bind_texture(context, info.bind_target, texture->texture_rgb.name);
+    apply_texture_blit_state(gl_info, &texture->texture_rgb, info.bind_target,
level, filter);
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL,
level);
+
+    context_get_rt_size(context, &dst_size);
+    w = dst_size.cx;
+    h = dst_size.cy;
+
+    quad[0].x = dst_rect->left * 2.0f / w - 1.0f;
+    quad[0].y = dst_rect->top * 2.0f / h - 1.0f;
+    quad[0].texcoord = info.texcoords[0];
+
+    quad[1].x = dst_rect->right * 2.0f / w - 1.0f;
+    quad[1].y = dst_rect->top * 2.0f / h - 1.0f;
+    quad[1].texcoord = info.texcoords[1];
+
+    quad[2].x = dst_rect->left * 2.0f / w - 1.0f;
+    quad[2].y = dst_rect->bottom * 2.0f / h - 1.0f;
+    quad[2].texcoord = info.texcoords[2];
+
+    quad[3].x = dst_rect->right * 2.0f / w - 1.0f;
+    quad[3].y = dst_rect->bottom * 2.0f / h - 1.0f;
+    quad[3].texcoord = info.texcoords[3];
+
+    /* Draw a quad. */
+    if (gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
+    {
+        if (!context->blit_vbo)
+            GL_EXTCALL(glGenBuffers(1, &context->blit_vbo));
+        GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, context->blit_vbo));
+
+        context_unload_vertex_data(context);
+        context_unload_numbered_arrays(context);
+
+        GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW));
+        GL_EXTCALL(glVertexAttribPointer(0, 2, GL_FLOAT, FALSE, sizeof(*quad), NULL));
+        GL_EXTCALL(glVertexAttribPointer(1, 3, GL_FLOAT, FALSE, sizeof(*quad),
+                (void *)FIELD_OFFSET(struct blit_vertex, texcoord)));
+
+        GL_EXTCALL(glEnableVertexAttribArray(0));
+        GL_EXTCALL(glEnableVertexAttribArray(1));
+
+        gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+        GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
+        GL_EXTCALL(glDisableVertexAttribArray(1));
+        GL_EXTCALL(glDisableVertexAttribArray(0));
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+
+        for (i = 0; i < ARRAY_SIZE(quad); ++i)
+        {
+            GL_EXTCALL(glVertexAttrib3fv(1, &quad[i].texcoord.x));
+            GL_EXTCALL(glVertexAttrib2fv(0, &quad[i].x));
+        }
+
+        gl_info->gl_ops.gl.p_glEnd();
+    }
+    checkGLcall("draw");
+
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL,
texture->level_count - 1);
+    context_bind_texture(context, info.bind_target, 0);
+}
+
+/* Context activation is done by the caller. */
+void context_draw_textured_quad(struct wined3d_context *context, struct wined3d_texture
*texture,
+        unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect,
+        enum wined3d_texture_filter_type filter)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_blt_info info;
+    unsigned int level;
+
+    texture2d_get_blt_info(texture, sub_resource_idx, src_rect, &info);
+
+    gl_info->gl_ops.gl.p_glEnable(info.bind_target);
+    checkGLcall("glEnable(bind_target)");
+
+    level = sub_resource_idx % texture->level_count;
+    context_bind_texture(context, info.bind_target, texture->texture_rgb.name);
+    apply_texture_blit_state(gl_info, &texture->texture_rgb, info.bind_target,
level, filter);
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL,
level);
+    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    checkGLcall("glTexEnvi");
+
+    /* Draw a quad. */
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[0].x);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->top);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[1].x);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->top);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[2].x);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->bottom);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[3].x);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->bottom);
+    gl_info->gl_ops.gl.p_glEnd();
+
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL,
texture->level_count - 1);
+    context_bind_texture(context, info.bind_target, 0);
+}
diff --git a/dll/directx/wine/wined3d/cs.c b/dll/directx/wine/wined3d/cs.c
index 460fe12c7d..eb24d94e9a 100644
--- a/dll/directx/wine/wined3d/cs.c
+++ b/dll/directx/wine/wined3d/cs.c
@@ -33,8 +33,8 @@ enum wined3d_cs_op
     WINED3D_CS_OP_DRAW,
     WINED3D_CS_OP_FLUSH,
     WINED3D_CS_OP_SET_PREDICATION,
-    WINED3D_CS_OP_SET_VIEWPORT,
-    WINED3D_CS_OP_SET_SCISSOR_RECT,
+    WINED3D_CS_OP_SET_VIEWPORTS,
+    WINED3D_CS_OP_SET_SCISSOR_RECTS,
     WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
     WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
     WINED3D_CS_OP_SET_VERTEX_DECLARATION,
@@ -94,7 +94,7 @@ struct wined3d_cs_present
     struct wined3d_swapchain *swapchain;
     RECT src_rect;
     RECT dst_rect;
-    DWORD swap_interval;
+    unsigned int swap_interval;
     DWORD flags;
 };
@@ -138,16 +138,18 @@ struct wined3d_cs_set_predication
     BOOL value;
 };
-struct wined3d_cs_set_viewport
+struct wined3d_cs_set_viewports
 {
     enum wined3d_cs_op opcode;
-    struct wined3d_viewport viewport;
+    unsigned int viewport_count;
+    struct wined3d_viewport viewports[1];
 };
-struct wined3d_cs_set_scissor_rect
+struct wined3d_cs_set_scissor_rects
 {
     enum wined3d_cs_op opcode;
-    RECT rect;
+    unsigned int rect_count;
+    RECT rects[1];
 };
 struct wined3d_cs_set_rendertarget_view
@@ -406,9 +408,7 @@ struct wined3d_cs_update_sub_resource
     unsigned int sub_resource_idx;
     struct wined3d_box box;
     struct wined3d_sub_resource_data data;
-#if defined(STAGING_CSMT)
     BYTE copy_data[1];
-#endif /* STAGING_CSMT */
 };
 struct wined3d_cs_add_dirty_texture_region
@@ -456,12 +456,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void
*data)
     swapchain = op->swapchain;
     wined3d_swapchain_set_window(swapchain, op->dst_window_override);
-
-    if (op->swap_interval && swapchain->desc.swap_interval !=
op->swap_interval)
-    {
-        swapchain->desc.swap_interval = op->swap_interval;
-        swapchain_update_swap_interval(swapchain);
-    }
+    wined3d_swapchain_set_swap_interval(swapchain, op->swap_interval);
     swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect,
&op->dst_rect, op->flags);
@@ -476,7 +471,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void
*data)
 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
-        DWORD swap_interval, DWORD flags)
+        unsigned int swap_interval, DWORD flags)
 {
     struct wined3d_cs_present *op;
     unsigned int i;
@@ -502,9 +497,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct
wined3d_swapchain *sw
     cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
     /* Limit input latency by limiting the number of presents that we can get
-     * ahead of the worker thread. We have a constant limit here, but
-     * IDXGIDevice1 allows tuning this. */
-    while (pending > 1)
+     * ahead of the worker thread. */
+    while (pending >= swapchain->max_frame_latency)
     {
         wined3d_pause();
         pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0);
@@ -538,19 +532,24 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count,
const RECT *
 {
     unsigned int rt_count = cs->device->adapter->gl_info.limits.buffers;
     const struct wined3d_state *state = &cs->device->state;
-    const struct wined3d_viewport *vp = &state->viewport;
+    const struct wined3d_viewport *vp = &state->viewports[0];
+    struct wined3d_rendertarget_view *view;
     struct wined3d_cs_clear *op;
+    RECT view_rect;
     unsigned int i;
     op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_clear,
rects[rect_count]),
             WINED3D_CS_QUEUE_DEFAULT);
     op->opcode = WINED3D_CS_OP_CLEAR;
     op->flags = flags;
-    op->rt_count = rt_count;
+    if (flags & WINED3DCLEAR_TARGET)
+        op->rt_count = rt_count;
+    else
+        op->rt_count = 0;
     op->fb = &cs->fb;
     SetRect(&op->draw_rect, vp->x, vp->y, vp->x + vp->width, vp->y
+ vp->height);
     if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
-        IntersectRect(&op->draw_rect, &op->draw_rect,
&state->scissor_rect);
+        IntersectRect(&op->draw_rect, &op->draw_rect,
&state->scissor_rects[0]);
     op->color = *color;
     op->depth = depth;
     op->stencil = stencil;
@@ -561,12 +560,21 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count,
const RECT *
     {
         for (i = 0; i < rt_count; ++i)
         {
-            if (state->fb->render_targets[i])
-
wined3d_resource_acquire(state->fb->render_targets[i]->resource);
+            if ((view = state->fb->render_targets[i]))
+            {
+                SetRect(&view_rect, 0, 0, view->width, view->height);
+                IntersectRect(&op->draw_rect, &op->draw_rect,
&view_rect);
+                wined3d_resource_acquire(view->resource);
+            }
         }
     }
     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
-        wined3d_resource_acquire(state->fb->depth_stencil->resource);
+    {
+        view = state->fb->depth_stencil;
+        SetRect(&view_rect, 0, 0, view->width, view->height);
+        IntersectRect(&op->draw_rect, &op->draw_rect, &view_rect);
+        wined3d_resource_acquire(view->resource);
+    }
     cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
 }
@@ -774,6 +782,7 @@ void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs *cs,
 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
+    const struct wined3d_shader *geometry_shader;
     struct wined3d_state *state = &cs->state;
     const struct wined3d_cs_draw *op = data;
     int load_base_vertex_idx;
@@ -793,6 +802,8 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void
*data)
     if (state->gl_primitive_type != op->primitive_type)
     {
+        if ((geometry_shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) &&
!geometry_shader->function)
+            device_invalidate_state(cs->device,
STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY));
         if (state->gl_primitive_type == GL_POINTS || op->primitive_type ==
GL_POINTS)
             device_invalidate_state(cs->device, STATE_POINT_ENABLE);
         state->gl_primitive_type = op->primitive_type;
@@ -958,40 +969,53 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct
wined3d_query
     cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
 }
-static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_viewports(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_cs_set_viewport *op = data;
+    const struct wined3d_cs_set_viewports *op = data;
-    cs->state.viewport = op->viewport;
+    if (op->viewport_count)
+        memcpy(cs->state.viewports, op->viewports, op->viewport_count *
sizeof(*op->viewports));
+    else
+        memset(cs->state.viewports, 0, sizeof(*cs->state.viewports));
+    cs->state.viewport_count = op->viewport_count;
     device_invalidate_state(cs->device, STATE_VIEWPORT);
 }
-void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport
*viewport)
+void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count,
+        const struct wined3d_viewport *viewports)
 {
-    struct wined3d_cs_set_viewport *op;
+    struct wined3d_cs_set_viewports *op;
-    op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
-    op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
-    op->viewport = *viewport;
+    op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_set_viewports,
viewports[viewport_count]),
+            WINED3D_CS_QUEUE_DEFAULT);
+    op->opcode = WINED3D_CS_OP_SET_VIEWPORTS;
+    memcpy(op->viewports, viewports, viewport_count * sizeof(*viewports));
+    op->viewport_count = viewport_count;
     cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
 }
-static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_cs_set_scissor_rect *op = data;
+    const struct wined3d_cs_set_scissor_rects *op = data;
-    cs->state.scissor_rect = op->rect;
+    if (op->rect_count)
+        memcpy(cs->state.scissor_rects, op->rects, op->rect_count *
sizeof(*op->rects));
+    else
+        SetRectEmpty(cs->state.scissor_rects);
+    cs->state.scissor_rect_count = op->rect_count;
     device_invalidate_state(cs->device, STATE_SCISSORRECT);
 }
-void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
+void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count,
const RECT *rects)
 {
-    struct wined3d_cs_set_scissor_rect *op;
+    struct wined3d_cs_set_scissor_rects *op;
-    op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
-    op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
-    op->rect = *rect;
+    op = cs->ops->require_space(cs, FIELD_OFFSET(struct
wined3d_cs_set_scissor_rects, rects[rect_count]),
+            WINED3D_CS_QUEUE_DEFAULT);
+    op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECTS;
+    memcpy(op->rects, rects, rect_count * sizeof(*rects));
+    op->rect_count = rect_count;
     cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
 }
@@ -1023,16 +1047,14 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct
wined3d_cs *cs, const
     struct wined3d_device *device = cs->device;
     struct wined3d_rendertarget_view *prev;
-    if ((prev = cs->state.fb->depth_stencil))
+    if ((prev = cs->state.fb->depth_stencil) && prev->resource->type
!= WINED3D_RTYPE_BUFFER)
     {
-        struct wined3d_surface *prev_surface =
wined3d_rendertarget_view_get_surface(prev);
+        struct wined3d_texture *prev_texture = texture_from_resource(prev->resource);
-        if (prev_surface && (device->swapchains[0]->desc.flags &
WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
-                || prev_surface->container->flags & WINED3D_TEXTURE_DISCARD))
-        {
-            wined3d_texture_validate_location(prev_surface->container,
+        if (device->swapchains[0]->desc.flags &
WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
+                || prev_texture->flags & WINED3D_TEXTURE_DISCARD)
+            wined3d_texture_validate_location(prev_texture,
                     prev->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
-        }
     }
     cs->fb.depth_stencil = op->view;
@@ -1470,7 +1492,7 @@ static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs, const vo
     const struct wined3d_cs_set_rasterizer_state *op = data;
     cs->state.rasterizer_state = op->state;
-    device_invalidate_state(cs->device, STATE_FRONTFACE);
+    device_invalidate_state(cs->device, STATE_RASTERIZER);
 }
 void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs,
@@ -2059,23 +2081,6 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs,
const void *
                 buffer_from_resource(op->src_resource), op->src_box.left,
                 op->src_box.right - op->src_box.left);
     }
-    else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D)
-    {
-        struct wined3d_surface *dst_surface, *src_surface;
-        struct wined3d_texture *dst_texture, *src_texture;
-        RECT dst_rect, src_rect;
-
-        dst_texture = texture_from_resource(op->dst_resource);
-        src_texture = texture_from_resource(op->src_resource);
-        dst_surface =
dst_texture->sub_resources[op->dst_sub_resource_idx].u.surface;
-        src_surface =
src_texture->sub_resources[op->src_sub_resource_idx].u.surface;
-        SetRect(&dst_rect, op->dst_box.left, op->dst_box.top,
op->dst_box.right, op->dst_box.bottom);
-        SetRect(&src_rect, op->src_box.left, op->src_box.top,
op->src_box.right, op->src_box.bottom);
-
-        if (FAILED(wined3d_surface_blt(dst_surface, &dst_rect, src_surface,
-                &src_rect, op->flags, &op->fx, op->filter)))
-            FIXME("Blit failed.\n");
-    }
     else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_3D)
     {
         struct wined3d_texture *src_texture, *dst_texture;
@@ -2110,13 +2115,6 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs,
const void *
             goto error;
         }
-        if (op->src_box.left || op->src_box.top || op->src_box.front)
-        {
-            FIXME("Source box %s not supported for %s resources.\n",
-                    debug_box(&op->src_box),
debug_d3dresourcetype(op->dst_resource->type));
-            goto error;
-        }
-
         dst_texture = texture_from_resource(op->dst_resource);
         src_texture = texture_from_resource(op->src_resource);
@@ -2151,8 +2149,9 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs,
const void *
                 &row_pitch, &slice_pitch);
         wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
-        wined3d_texture_upload_data(dst_texture, op->dst_sub_resource_idx, context,
&op->dst_box,
-                wined3d_const_bo_address(&addr), row_pitch, slice_pitch);
+        wined3d_texture_upload_data(dst_texture, op->dst_sub_resource_idx, context,
+                dst_texture->resource.format, &op->src_box,
wined3d_const_bo_address(&addr),
+                row_pitch, slice_pitch, op->dst_box.left, op->dst_box.top,
op->dst_box.front, FALSE);
         wined3d_texture_validate_location(dst_texture, op->dst_sub_resource_idx,
WINED3D_LOCATION_TEXTURE_RGB);
         wined3d_texture_invalidate_location(dst_texture, op->dst_sub_resource_idx,
~WINED3D_LOCATION_TEXTURE_RGB);
@@ -2160,7 +2159,10 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs,
const void *
     }
     else
     {
-        FIXME("Not implemented for %s resources.\n",
debug_d3dresourcetype(op->dst_resource->type));
+        if (FAILED(texture2d_blt(texture_from_resource(op->dst_resource),
op->dst_sub_resource_idx,
+                &op->dst_box, texture_from_resource(op->src_resource),
op->src_sub_resource_idx,
+                &op->src_box, op->flags, &op->fx, op->filter)))
+            FIXME("Blit failed.\n");
     }
 error:
@@ -2209,6 +2211,7 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs, const voi
     struct wined3d_const_bo_address addr;
     struct wined3d_context *context;
     struct wined3d_texture *texture;
+    struct wined3d_box src_box;
     context = context_acquire(cs->device, NULL, 0);
@@ -2245,8 +2248,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs, const voi
         wined3d_texture_load_location(texture, op->sub_resource_idx, context,
WINED3D_LOCATION_TEXTURE_RGB);
     wined3d_texture_bind_and_dirtify(texture, context, FALSE);
-    wined3d_texture_upload_data(texture, op->sub_resource_idx, context,
-            box, &addr, op->data.row_pitch, op->data.slice_pitch);
+    wined3d_box_set(&src_box, 0, 0, box->right - box->left, box->bottom -
box->top, 0, box->back - box->front);
+    wined3d_texture_upload_data(texture, op->sub_resource_idx, context,
texture->resource.format, &src_box,
+            &addr, op->data.row_pitch, op->data.slice_pitch, box->left,
box->top, box->front, FALSE);
     wined3d_texture_validate_location(texture, op->sub_resource_idx,
WINED3D_LOCATION_TEXTURE_RGB);
     wined3d_texture_invalidate_location(texture, op->sub_resource_idx,
~WINED3D_LOCATION_TEXTURE_RGB);
@@ -2262,7 +2266,6 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs,
struct wined3d_r
         unsigned int slice_pitch)
 {
     struct wined3d_cs_update_sub_resource *op;
-#if defined(STAGING_CSMT)
     size_t data_size, size;
     if (resource->type != WINED3D_RTYPE_BUFFER && resource->format_flags
& WINED3DFMT_FLAG_BLOCKS)
@@ -2308,7 +2311,6 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs,
struct wined3d_r
 no_async:
     wined3d_resource_wait_idle(resource);
-#endif /* STAGING_CSMT */
     op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_MAP);
     op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE;
@@ -2322,10 +2324,6 @@ no_async:
     wined3d_resource_acquire(resource);
     cs->ops->submit(cs, WINED3D_CS_QUEUE_MAP);
-#if !defined(STAGING_CSMT)
-    /* The data pointer may go away, so we need to wait until it is read.
-     * Copying the data may be faster if it's small. */
-#endif /* STAGING_CSMT */
     cs->ops->finish(cs, WINED3D_CS_QUEUE_MAP);
 }
@@ -2466,8 +2464,8 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs
*cs, const void
     /* WINED3D_CS_OP_DRAW                        */ wined3d_cs_exec_draw,
     /* WINED3D_CS_OP_FLUSH                       */ wined3d_cs_exec_flush,
     /* WINED3D_CS_OP_SET_PREDICATION             */ wined3d_cs_exec_set_predication,
-    /* WINED3D_CS_OP_SET_VIEWPORT                */ wined3d_cs_exec_set_viewport,
-    /* WINED3D_CS_OP_SET_SCISSOR_RECT            */ wined3d_cs_exec_set_scissor_rect,
+    /* WINED3D_CS_OP_SET_VIEWPORTS               */ wined3d_cs_exec_set_viewports,
+    /* WINED3D_CS_OP_SET_SCISSOR_RECTS           */ wined3d_cs_exec_set_scissor_rects,
     /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW       */
wined3d_cs_exec_set_rendertarget_view,
     /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW      */
wined3d_cs_exec_set_depth_stencil_view,
     /* WINED3D_CS_OP_SET_VERTEX_DECLARATION      */
wined3d_cs_exec_set_vertex_declaration,
@@ -2508,13 +2506,11 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs
*cs, const void
     /* WINED3D_CS_OP_GENERATE_MIPMAPS            */ wined3d_cs_exec_generate_mipmaps,
 };
-#if defined(STAGING_CSMT)
 static BOOL wined3d_cs_st_check_space(struct wined3d_cs *cs, size_t size, enum
wined3d_cs_queue_id queue_id)
 {
     return TRUE;
 }
-#endif /* STAGING_CSMT */
 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size, enum
wined3d_cs_queue_id queue_id)
 {
     if (size > (cs->data_size - cs->end))
@@ -2568,9 +2564,7 @@ static void wined3d_cs_st_finish(struct wined3d_cs *cs, enum
wined3d_cs_queue_id
 static const struct wined3d_cs_ops wined3d_cs_st_ops =
 {
-#if defined(STAGING_CSMT)
     wined3d_cs_st_check_space,
-#endif /* STAGING_CSMT */
     wined3d_cs_st_require_space,
     wined3d_cs_st_submit,
     wined3d_cs_st_finish,
@@ -2607,7 +2601,6 @@ static void wined3d_cs_mt_submit(struct wined3d_cs *cs, enum
wined3d_cs_queue_id
     wined3d_cs_queue_submit(&cs->queue[queue_id], cs);
 }
-#if defined(STAGING_CSMT)
 static BOOL wined3d_cs_queue_check_space(struct wined3d_cs_queue *queue, size_t size)
 {
     size_t queue_size = ARRAY_SIZE(queue->data);
@@ -2621,7 +2614,6 @@ static BOOL wined3d_cs_queue_check_space(struct wined3d_cs_queue
*queue, size_t
     return (remaining >= packet_size);
 }
-#endif /* STAGING_CSMT */
 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size_t size,
struct wined3d_cs *cs)
 {
     size_t queue_size = ARRAY_SIZE(queue->data);
@@ -2683,7 +2675,6 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue, size
     return packet->data;
 }
-#if defined(STAGING_CSMT)
 static BOOL wined3d_cs_mt_check_space(struct wined3d_cs *cs, size_t size, enum
wined3d_cs_queue_id queue_id)
 {
     if (cs->thread_id == GetCurrentThreadId())
@@ -2692,7 +2683,6 @@ static BOOL wined3d_cs_mt_check_space(struct wined3d_cs *cs, size_t
size, enum w
     return wined3d_cs_queue_check_space(&cs->queue[queue_id], size);
 }
-#endif /* STAGING_CSMT */
 static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, enum
wined3d_cs_queue_id queue_id)
 {
     if (cs->thread_id == GetCurrentThreadId())
@@ -2715,9 +2705,7 @@ static void wined3d_cs_mt_finish(struct wined3d_cs *cs, enum
wined3d_cs_queue_id
 static const struct wined3d_cs_ops wined3d_cs_mt_ops =
 {
-#if defined(STAGING_CSMT)
     wined3d_cs_mt_check_space,
-#endif /* STAGING_CSMT */
     wined3d_cs_mt_require_space,
     wined3d_cs_mt_submit,
     wined3d_cs_mt_finish,
diff --git a/dll/directx/wine/wined3d/device.c b/dll/directx/wine/wined3d/device.c
index e2b27e0cf4..8b4b3f9bb2 100644
--- a/dll/directx/wine/wined3d/device.c
+++ b/dll/directx/wine/wined3d/device.c
@@ -99,7 +99,7 @@ GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type
primitive_type)
     }
 }
-static enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type)
+enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type)
 {
     switch (primitive_type)
     {
@@ -226,11 +226,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT
rt_count, c
         float depth, DWORD stencil)
 {
     struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL;
-    struct wined3d_surface *target = rtv ? wined3d_rendertarget_view_get_surface(rtv) :
NULL;
     struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
-    struct wined3d_surface *depth_stencil = dsv ?
wined3d_rendertarget_view_get_surface(dsv) : NULL;
     const struct wined3d_state *state = &device->cs->state;
+    struct wined3d_texture *depth_stencil = NULL;
     const struct wined3d_gl_info *gl_info;
+    struct wined3d_texture *target = NULL;
     UINT drawable_width, drawable_height;
     struct wined3d_color corrected_color;
     struct wined3d_context *context;
@@ -238,10 +238,19 @@ void device_clear_render_targets(struct wined3d_device *device, UINT
rt_count, c
     BOOL render_offscreen;
     unsigned int i;
-    if (target)
-        context = context_acquire(device, target->container,
rtv->sub_resource_idx);
+    if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER)
+    {
+        target = texture_from_resource(rtv->resource);
+        context = context_acquire(device, target, rtv->sub_resource_idx);
+    }
     else
+    {
         context = context_acquire(device, NULL, 0);
+    }
+
+    if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
+        depth_stencil = texture_from_resource(dsv->resource);
+
     if (!context->valid)
     {
         context_release(context);
@@ -281,11 +290,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT
rt_count, c
     }
     else
     {
-        unsigned int ds_level = dsv->sub_resource_idx %
depth_stencil->container->level_count;
+        unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count;
         render_offscreen = TRUE;
-        drawable_width =
wined3d_texture_get_level_pow2_width(depth_stencil->container, ds_level);
-        drawable_height =
wined3d_texture_get_level_pow2_height(depth_stencil->container, ds_level);
+        drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level);
+        drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level);
     }
     if (depth_stencil)
@@ -402,9 +411,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT
rt_count, c
             gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height -
draw_rect->bottom,
                         draw_rect->right - draw_rect->left, draw_rect->bottom -
draw_rect->top);
         }
-        checkGLcall("glScissor");
         gl_info->gl_ops.gl.p_glClear(clear_mask);
-        checkGLcall("glClear");
     }
     else
     {
@@ -439,16 +446,14 @@ void device_clear_render_targets(struct wined3d_device *device, UINT
rt_count, c
                 gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height -
current_rect.bottom,
                           current_rect.right - current_rect.left, current_rect.bottom -
current_rect.top);
             }
-            checkGLcall("glScissor");
-
             gl_info->gl_ops.gl.p_glClear(clear_mask);
-            checkGLcall("glClear");
         }
     }
+    context->scissor_rect_count = WINED3D_MAX_VIEWPORTS;
+    checkGLcall("clear");
-    if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET
-            && target->container->swapchain &&
target->container->swapchain->front_buffer == target->container))
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts.
*/
+    if (flags & WINED3DCLEAR_TARGET && target->swapchain &&
target->swapchain->front_buffer == target)
+        gl_info->gl_ops.gl.p_glFlush();
     context_release(context);
 }
@@ -677,12 +682,11 @@ static void create_dummy_textures(struct wined3d_device *device,
struct wined3d_
     if (gl_info->supported[EXT_TEXTURE_ARRAY])
     {
-
         gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array);
         TRACE("Dummy 1D array texture given name %u.\n",
textures->tex_1d_array);
         gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY,
textures->tex_1d_array);
         gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0,
-                GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+                    GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
         gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array);
         TRACE("Dummy 2D array texture given name %u.\n",
textures->tex_2d_array);
@@ -752,8 +756,8 @@ static void destroy_dummy_textures(struct wined3d_device *device,
struct wined3d
     if (gl_info->supported[EXT_TEXTURE_ARRAY])
     {
-        gl_info->gl_ops.gl.p_glDeleteTextures(1,
&dummy_textures->tex_1d_array);
         gl_info->gl_ops.gl.p_glDeleteTextures(1,
&dummy_textures->tex_2d_array);
... 11015 lines suppressed ...