[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 3.9. CORE-14656
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 27 May 2018 02:52:04 +0000 (03:52 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 27 May 2018 02:52:04 +0000 (03:52 +0100)
42 files changed:
dll/directx/wine/d3d8/d3d8_private.h
dll/directx/wine/d3d8/device.c
dll/directx/wine/d3d8/directx.c
dll/directx/wine/d3d8/swapchain.c
dll/directx/wine/d3d9/d3d9_private.h
dll/directx/wine/d3d9/device.c
dll/directx/wine/d3d9/directx.c
dll/directx/wine/d3d9/swapchain.c
dll/directx/wine/d3d9/texture.c
dll/directx/wine/ddraw/ddraw.c
dll/directx/wine/ddraw/ddraw_private.h
dll/directx/wine/ddraw/device.c
dll/directx/wine/ddraw/executebuffer.c
dll/directx/wine/ddraw/palette.c
dll/directx/wine/ddraw/surface.c
dll/directx/wine/ddraw/utils.c
dll/directx/wine/ddraw/viewport.c
dll/directx/wine/wined3d/arb_program_shader.c
dll/directx/wine/wined3d/ati_fragment_shader.c
dll/directx/wine/wined3d/buffer.c
dll/directx/wine/wined3d/context.c
dll/directx/wine/wined3d/cs.c
dll/directx/wine/wined3d/device.c
dll/directx/wine/wined3d/directx.c
dll/directx/wine/wined3d/glsl_shader.c
dll/directx/wine/wined3d/nvidia_texture_shader.c
dll/directx/wine/wined3d/resource.c
dll/directx/wine/wined3d/shader.c
dll/directx/wine/wined3d/shader_sm4.c
dll/directx/wine/wined3d/state.c
dll/directx/wine/wined3d/stateblock.c
dll/directx/wine/wined3d/surface.c
dll/directx/wine/wined3d/swapchain.c
dll/directx/wine/wined3d/texture.c
dll/directx/wine/wined3d/utils.c
dll/directx/wine/wined3d/view.c
dll/directx/wine/wined3d/wined3d.spec
dll/directx/wine/wined3d/wined3d_gl.h
dll/directx/wine/wined3d/wined3d_main.c
dll/directx/wine/wined3d/wined3d_private.h
media/doc/README.WINE
sdk/include/reactos/wine/wined3d.h

index cba5dd6..3fbc096 100644 (file)
@@ -166,10 +166,11 @@ struct d3d8_swapchain
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
     IDirect3DDevice8 *parent_device;
     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,
 };
 
 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
 {
 
 struct d3d8_surface
 {
index 5daf6f4..616886b 100644 (file)
@@ -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,
 }
 
 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;
 {
     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;
             = 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)
 }
 
 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)
 {
 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;
     }
         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;
 
     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->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)
     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->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;
     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->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);
     /* 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);
     else
         caps->VertexShaderVersion = D3DVS_VERSION(0, 0);
     caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst);
-
-    caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
 }
 
 /* Handle table functions */
 }
 
 /* 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;
     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",
     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 (!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;
         *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;
 }
 
     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;
             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);
         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);
 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);
 
     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;
     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;
 
     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;
     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();
     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;
     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)
 {
 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,
 }
 
 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);
 }
 
         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)
 {
         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;
 }
 
     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);
 
 
     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;
     {
         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_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,
 };
     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();
 
     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))))
 
     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);
 
     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);
 
     device->d3d_parent = &parent->IDirect3D8_iface;
     IDirect3D8_AddRef(device->d3d_parent);
index 6e8f93a..68300c0 100644 (file)
@@ -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
     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;
 
     d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
     d3d8->refcount = 1;
index 3a588b5..39e3b23 100644 (file)
@@ -105,7 +105,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_swapchain_Present(IDirect3DSwapChai
 
     wined3d_mutex_lock();
     hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
 
     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;
     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,
 };
 
 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;
 {
     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,
 
     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,
 }
 
 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;
 {
     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 (!(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);
     {
         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
         heap_free(object);
index ba19e5f..c50aabf 100644 (file)
@@ -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,
 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
 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;
 
     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;
     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;
     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,
 };
 
 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
 {
 
 struct d3d9_surface
 {
index bc73699..2f3ad28 100644 (file)
@@ -231,7 +231,7 @@ static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effe
 }
 
 void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
 }
 
 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;
 {
     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;
             = 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)
 }
 
 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)
 {
 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;
     }
         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;
 
     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->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)
     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->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;
     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;
     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",
     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 (!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;
         *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;
 }
 
     return hr;
 }
@@ -934,6 +970,8 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
         }
         else
         {
         }
         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;
             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;
         }
 
             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)
         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);
         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",
     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)
     {
     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;
         {
             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),
     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);
 
     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();
     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;
     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();
     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;
     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);
     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;
     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();
     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;
     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();
     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;
     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)
 {
 /* 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,
 }
 
 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);
         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",
     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)
     {
     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;
         {
             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)
 {
 
 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);
 
     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)
 {
 
     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)
 }
 
 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);
 }
 
         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)
 {
         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;
 }
 
     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);
 
 
     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;
     {
         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_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,
 };
     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;
     }
         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)
     {
 
     for (i = 0; i < count; ++i)
     {
-        present_parameters_from_wined3d_swapchain_desc(&parameters[i], &swapchain_desc[i]);
+        present_parameters_from_wined3d_swapchain_desc(&parameters[i],
+                &swapchain_desc[i], parameters[i].PresentationInterval);
     }
 
     wined3d_mutex_unlock();
     }
 
     wined3d_mutex_unlock();
index 644766c..98f4a99 100644 (file)
@@ -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);
 
     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)
     {
     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
     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;
 
     if (!extended)
         flags |= WINED3D_VIDMEM_ACCOUNTING;
index dbb3f45..d303f3f 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
 
 
 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);
 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,
 
     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;
     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;
 {
     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);
 
     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();
     wined3d_mutex_unlock();
-    present_parameters_from_wined3d_swapchain_desc(parameters, &desc);
+    present_parameters_from_wined3d_swapchain_desc(parameters, &desc, presentation_interval);
 
     return D3D_OK;
 }
 
     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,
 };
 
 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;
 {
     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,
 
     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,
 }
 
 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;
 {
     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 (!(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);
     {
         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
         heap_free(object);
index c97fa6b..7b74ac5 100644 (file)
@@ -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;
         }
             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;
         texture->autogen_filter_type = D3DTEXF_LINEAR;
-        levels = 0;
     }
     else
     {
     }
     else
     {
index e5205c0..6b5ccec 100644 (file)
@@ -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_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;
     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->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;
 }
 
     return DD_OK;
 }
@@ -4909,18 +4910,19 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw)
     ddraw->device_state = DDRAW_DEVICE_STATE_OK;
 }
 
     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;
 
         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. */
 
     /* 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;
     {
         *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;
 }
 
     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;
 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);
         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);
 
     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,
 
     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;
     }
 
     {
         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;
 }
 
     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_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,
 };
     device_parent_create_swapchain_texture,
     device_parent_create_swapchain,
 };
index 1454e80..9757008 100644 (file)
@@ -59,14 +59,15 @@ struct FvfToDecl
 #define DDRAW_NO3D              0x00000008
 #define DDRAW_SCL_DDRAW1        0x00000010
 #define DDRAW_SCL_RECURSIVE     0x00000020
 #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 \
 
 #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
 {
 
 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,
         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)
 {
 
 static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface)
 {
index 24dbd3b..799b2bc 100644 (file)
@@ -5296,25 +5296,12 @@ static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWO
     return hr;
 }
 
     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);
 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);
     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;
 
     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;
     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;
 
     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;
     wined3d_mutex_unlock();
 
     return D3D_OK;
@@ -5353,21 +5356,6 @@ static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *ifac
     return hr;
 }
 
     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);
 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();
         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;
     wined3d_mutex_unlock();
 
     viewport->dwX = wined3d_viewport.x;
index 17bea27..e2c4fc1 100644 (file)
@@ -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_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:
                             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;
     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);
 
 
     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;
 
     /* 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;
     }
 
         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);
     {
         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;
 
                 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);
     }
 
         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);
 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);
 
 
     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))
     {
 
     if (TRACE_ON(ddraw))
     {
index 5148832..87aec96 100644 (file)
@@ -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)
     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();
 
 
     wined3d_mutex_unlock();
 
index 5eefc22..e188396 100644 (file)
@@ -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. */
  * 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;
 
     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);
     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 (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;
 
     {
         /* 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)))
     }
 
     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);
             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);
     }
     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)
     }
 
     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,
     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)
     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;
     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);
 }
 
     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)
 {
 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;
 
     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++)
     {
         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)
     }
 
     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;
 
     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)
     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))
         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;
     }
 
         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 (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;
             }
         }
                     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 (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;
         }
     }
                 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)
     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);
 
     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)
     {
         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();
 
     }
     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)
     }
 
     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))
     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)
     wined3d_mutex_unlock();
 
     switch(hr)
index 65f24dc..b0a028d 100644 (file)
@@ -570,7 +570,7 @@ unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags)
     unsigned int wined3d_flags;
 
     wined3d_flags = flags & handled;
     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;
         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;
         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);
 
     if (flags)
         FIXME("Unhandled flags %#x.\n", flags);
index 6ef3226..f2caf20 100644 (file)
@@ -249,109 +249,118 @@ static HRESULT WINAPI d3d_viewport_Initialize(IDirect3DViewport3 *iface, IDirect
     return DDERR_ALREADYINITIALIZED;
 }
 
     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();
 
 
     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;
         D3DVIEWPORT vp1;
+
         vp1.dwSize = sizeof(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.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");
     }
 
     if (TRACE_ON(ddraw))
     {
         TRACE("  returning D3DVIEWPORT :\n");
-        _dump_D3DVIEWPORT(lpData);
+        _dump_D3DVIEWPORT(vp);
     }
 
     wined3d_mutex_unlock();
 
     }
 
     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;
     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");
 
     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, &current_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, &current_viewport)))
+    {
+        if (current_viewport == iface)
+            viewport_activate(viewport, FALSE);
+        IDirect3DViewport3_Release(current_viewport);
+    }
+
     wined3d_mutex_unlock();
 
     wined3d_mutex_unlock();
 
-    return DD_OK;
+    return D3D_OK;
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
@@ -882,53 +891,44 @@ static HRESULT WINAPI d3d_viewport_NextLight(IDirect3DViewport3 *iface,
  * IDirect3DViewport2 Methods.
  *****************************************************************************/
 
  * 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();
 
     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;
         D3DVIEWPORT2 vp2;
+
         vp2.dwSize = sizeof(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.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");
     }
 
     if (TRACE_ON(ddraw))
     {
         TRACE("  returning D3DVIEWPORT2 :\n");
-        _dump_D3DVIEWPORT2(lpData);
+        _dump_D3DVIEWPORT2(vp);
     }
 
     wined3d_mutex_unlock();
     }
 
     wined3d_mutex_unlock();
@@ -936,47 +936,64 @@ static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVI
     return D3D_OK;
 }
 
     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;
     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");
 
     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, &current_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, &current_viewport)))
+    {
+        if (current_viewport == iface)
+            viewport_activate(viewport, FALSE);
+        IDirect3DViewport3_Release(current_viewport);
+    }
+
     wined3d_mutex_unlock();
 
     return D3D_OK;
     wined3d_mutex_unlock();
 
     return D3D_OK;
index f86c167..4fbb3a5 100644 (file)
@@ -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 */
     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;
     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);
                         }
                             /* 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
                         {
                             /* 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);
     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;
 
     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:
             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)
             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";
                 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;
 
     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,
 }
 
 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;
 
 {
     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);
 
     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 (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;
             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);
 
 
         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";
             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";
             instr = "TXP";
-        } else {
+        }
+        else
+        {
             FIXME("Unexpected projection mode %d\n", settings->op[stage].projected);
             instr = "TXP";
         }
             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);
 
             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, "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, "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);
             }
 
                 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);
             }
                                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);
             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);
         }
             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)
         {
 
         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)
         {
                           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)
         {
                           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);
                           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);
         }
                           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);
 }
 
     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";
 {
     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");
 
     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");
 
     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 */
     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);
 
     /* 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[]
 {
     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)
     {
      */
     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");
         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");
 
         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");
         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
     {
     }
     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");
 
         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");
         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';
         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[]
 {
     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
     {
     }
     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");
         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';
         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
     }
     *luminance = 'a';
-
-    return TRUE;
 }
 
 /* Context activation is done by the caller. */
 }
 
 /* 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:
     {
         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:
             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:
             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:
             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;
 
     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)
         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,
 }
 
 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)
 {
         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_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;
     struct wined3d_arbfp_blitter *arbfp_blitter;
     struct wined3d_color_key alpha_test_key;
     struct wined3d_blitter *next;
+    unsigned int src_level;
     RECT s, d;
 
     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 (!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);
 
     }
 
     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))
     {
             && !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. */
 
         /* 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;
 
         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
         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);
         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;
 
     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;
     }
 
         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)
         {
 
         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
         {
             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;
         }
             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);
         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 */
     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);
 
 
     /* 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;
 }
 
     return dst_location;
 }
index 9d6837a..9a1cae3 100644 (file)
@@ -341,9 +341,8 @@ static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES])
             lowest_read = i;
         }
 
             lowest_read = i;
         }
 
-        if(lowest_write == -1 && op[i].dst == tempreg) {
+        if (lowest_write == -1 && op[i].tmp_dst)
             lowest_write = i;
             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) {
 
         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);
 
         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;
             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;
             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
-        } else {
+        else
             swizzle = GL_SWIZZLE_STR_DR_ATI;
             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,
         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].cop == WINED3D_TOP_DISABLE)
             break;
 
-        if(op[stage].projected == proj_none) {
+        if (op[stage].projected == WINED3D_PROJECTION_NONE)
             swizzle = GL_SWIZZLE_STR_ATI;
             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;
             swizzle = GL_SWIZZLE_STR_DR_ATI;
-        } else {
+        else
             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
-        }
 
         if (op_reads_texture(&op[stage]))
         {
 
         if (op_reads_texture(&op[stage]))
         {
@@ -624,14 +619,18 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES],
             break;
         }
 
             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;
 
             dstreg = tmparg;
-        } else {
+        }
+        else
+        {
             dstreg = GL_REG_0_ATI;
         }
 
             dstreg = GL_REG_0_ATI;
         }
 
index cae7ef8..9baf055 100644 (file)
@@ -615,10 +615,7 @@ static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer,
                 return TRUE;
 
             if (!wined3d_resource_allocate_sysmem(&buffer->resource))
                 return TRUE;
 
             if (!wined3d_resource_allocate_sysmem(&buffer->resource))
-            {
-                ERR("Failed to allocate system memory.\n");
                 return FALSE;
                 return FALSE;
-            }
             return TRUE;
 
         case WINED3D_LOCATION_BUFFER:
             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));
         }
 
         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);
         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;
 
     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);
     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,
 
     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;
 }
 
     return WINED3D_OK;
 }
index 8a8d952..0ee5b65 100644 (file)
@@ -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);
     }
         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)
         {
     {
         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);
     {
         gl_info->fbo_ops.glFramebufferTexture1D(fbo_target, attachment,
                 resource->target, resource->object, resource->level);
-        checkGLcall("glFramebufferTexture1D()");
     }
     else
     {
     }
     else
     {
@@ -253,6 +252,8 @@ static void context_dump_fbo_attachment(const struct wined3d_gl_info *gl_info, G
     }
     texture_type[] =
     {
     }
     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},
         {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);
     }
 
     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;
     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)
         {
         }
         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,
 
 /* 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;
 
 {
     struct fbo_entry *entry, *entry2;
 
@@ -784,32 +778,35 @@ static void context_apply_fbo_state(struct wined3d_context *context, GLenum targ
     }
     else
     {
     }
     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,
         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,
         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));
     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->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. */
 }
 
 /* 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);
 }
 
     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;
 
 
     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);
 }
 
     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;
 {
     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)
     {
 
     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;
         }
             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");
     }
 
         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. */
 /* 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_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);
     }
 
     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);
         }
             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);
 
         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;
     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;
     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 = 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());
             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);");
 
     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
     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);
 
     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;
     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;
 }
 
     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;
 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");
 }
 
     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);
 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);
                 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);
                 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);
                 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_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));
     }
         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;
         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));
 }
     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)
 {
 /* 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_texture *rt = context->current_rt.texture;
-    struct wined3d_surface *surface;
     DWORD rt_mask, *cur_mask;
     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)
     {
 
     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);
 
         {
             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
             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
     {
     }
     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;
     }
 
     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);
     }
     {
         context_check_fbo_status(context, GL_FRAMEBUFFER);
     }
-
-    SetupForBlit(device, context);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
     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
             }
 
             /* 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
         {
         }
         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
         }
     }
     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
     {
     }
     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;
     }
 
     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_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
 
     /* 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)
     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);
 
     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)
     {
 
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
+        struct wined3d_rendertarget_info ds_info = {{0}};
+
         if (!context->render_offscreen)
         {
         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
                     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;
             }
                 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);
         }
     }
                     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->numDirtyEntries = 0; /* This makes the whole list clean */
     context->last_was_blit = FALSE;
+    context->last_was_ffp_blit = FALSE;
 
     return TRUE;
 }
 
     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_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)
 }
 
 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");
 
     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);
 }
 
     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_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;
         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;
         }
                 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;
         }
 
         {
             WARN_(d3d_perf)("Using software emulation because application requested SVP.\n");
             emulation = TRUE;
         }
 
-
         if (emulation)
         {
             si_emulated = context->stream_info;
         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)
         {
         }
         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;
             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);
 
     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);
 }
     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, &current_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);
+}
index 460fe12..eb24d94 100644 (file)
@@ -33,8 +33,8 @@ enum wined3d_cs_op
     WINED3D_CS_OP_DRAW,
     WINED3D_CS_OP_FLUSH,
     WINED3D_CS_OP_SET_PREDICATION,
     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,
     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;
     struct wined3d_swapchain *swapchain;
     RECT src_rect;
     RECT dst_rect;
-    DWORD swap_interval;
+    unsigned int swap_interval;
     DWORD flags;
 };
 
     DWORD flags;
 };
 
@@ -138,16 +138,18 @@ struct wined3d_cs_set_predication
     BOOL value;
 };
 
     BOOL value;
 };
 
-struct wined3d_cs_set_viewport
+struct wined3d_cs_set_viewports
 {
     enum wined3d_cs_op opcode;
 {
     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;
 {
     enum wined3d_cs_op opcode;
-    RECT rect;
+    unsigned int rect_count;
+    RECT rects[1];
 };
 
 struct wined3d_cs_set_rendertarget_view
 };
 
 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;
     unsigned int sub_resource_idx;
     struct wined3d_box box;
     struct wined3d_sub_resource_data data;
-#if defined(STAGING_CSMT)
     BYTE copy_data[1];
     BYTE copy_data[1];
-#endif /* STAGING_CSMT */
 };
 
 struct wined3d_cs_add_dirty_texture_region
 };
 
 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);
 
     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);
 
 
     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,
 
 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;
 {
     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
     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);
     {
         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;
 {
     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;
     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;
     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])
     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;
     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)
         {
     {
         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))
         }
     }
     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);
 }
 
     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;
 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;
     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 (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;
         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);
 }
 
     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);
 }
 
     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);
 }
 
 
     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);
 }
 
     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);
 }
 
     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;
 
     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);
                     prev->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
-        }
     }
 
     cs->fb.depth_stencil = op->view;
     }
 
     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;
     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,
 }
 
 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);
     }
                 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;
     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;
         }
 
             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);
 
         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);
                 &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);
 
         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
     {
     }
     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:
     }
 
 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_const_bo_address addr;
     struct wined3d_context *context;
     struct wined3d_texture *texture;
+    struct wined3d_box src_box;
 
     context = context_acquire(cs->device, NULL, 0);
 
 
     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_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);
 
     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;
         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)
     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);
 
 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;
 
     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);
     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);
 }
 
     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_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,
     /* 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,
 };
 
     /* 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;
 }
 
 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))
 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 =
 {
 
 static const struct wined3d_cs_ops wined3d_cs_st_ops =
 {
-#if defined(STAGING_CSMT)
     wined3d_cs_st_check_space,
     wined3d_cs_st_check_space,
-#endif /* STAGING_CSMT */
     wined3d_cs_st_require_space,
     wined3d_cs_st_submit,
     wined3d_cs_st_finish,
     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);
 }
 
     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);
 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);
 }
 
     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);
 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;
 }
 
     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())
 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);
 }
 
     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())
 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 =
 {
 
 static const struct wined3d_cs_ops wined3d_cs_mt_ops =
 {
-#if defined(STAGING_CSMT)
     wined3d_cs_mt_check_space,
     wined3d_cs_mt_check_space,
-#endif /* STAGING_CSMT */
     wined3d_cs_mt_require_space,
     wined3d_cs_mt_submit,
     wined3d_cs_mt_finish,
     wined3d_cs_mt_require_space,
     wined3d_cs_mt_submit,
     wined3d_cs_mt_finish,
index e2b27e0..8b4b3f9 100644 (file)
@@ -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)
     {
 {
     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;
         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_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;
     const struct wined3d_state *state = &device->cs->state;
+    struct wined3d_texture *depth_stencil = NULL;
     const struct wined3d_gl_info *gl_info;
     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;
     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;
 
     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
     else
+    {
         context = context_acquire(device, NULL, 0);
         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);
     if (!context->valid)
     {
         context_release(context);
@@ -281,11 +290,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     }
     else
     {
     }
     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;
 
         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)
     }
 
     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);
         }
             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);
         gl_info->gl_ops.gl.p_glClear(clear_mask);
-        checkGLcall("glClear");
     }
     else
     {
     }
     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);
             }
                 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);
             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);
 }
 
     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])
     {
 
     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_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);
 
         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])
     {
 
     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);
         gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array);
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array);
     }
 
     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY])
     }
 
     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY])
@@ -1036,7 +1040,8 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object)
         return;
     }
     wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
         return;
     }
     wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
-    wined3d_arbfp_blitter_create(&device->blitter, device);
+    if (!wined3d_glsl_blitter_create(&device->blitter, device))
+        wined3d_arbfp_blitter_create(&device->blitter, device);
     wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
     wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
 
     wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
     wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
 
@@ -1084,7 +1089,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
         goto err_out;
     }
 
         goto err_out;
     }
 
-    if (swapchain_desc->backbuffer_count)
+    if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_usage & WINED3DUSAGE_RENDERTARGET)
     {
         struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
         struct wined3d_view_desc view_desc;
     {
         struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
         struct wined3d_view_desc view_desc;
@@ -1120,7 +1125,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     TRACE("All defaults now set up.\n");
 
     /* Clear the screen */
     TRACE("All defaults now set up.\n");
 
     /* Clear the screen */
-    if (swapchain->back_buffers && swapchain->back_buffers[0])
+    if (device->back_buffer_view)
         clear_flags |= WINED3DCLEAR_TARGET;
     if (swapchain_desc->enable_auto_depth_stencil)
         clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL;
         clear_flags |= WINED3DCLEAR_TARGET;
     if (swapchain_desc->enable_auto_depth_stencil)
         clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL;
@@ -1212,9 +1217,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
 
     wine_rb_clear(&device->samplers, device_free_sampler, NULL);
 
 
     wine_rb_clear(&device->samplers, device_free_sampler, NULL);
 
-#if defined(STAGING_CSMT)
     context_set_current(NULL);
     context_set_current(NULL);
-#endif /* STAGING_CSMT */
     wined3d_device_delete_opengl_contexts(device);
 
     if (device->fb.depth_stencil)
     wined3d_device_delete_opengl_contexts(device);
 
     if (device->fb.depth_stencil)
@@ -1928,13 +1931,24 @@ INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *devi
     return device->state.base_vertex_index;
 }
 
     return device->state.base_vertex_index;
 }
 
-void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport)
+void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count,
+        const struct wined3d_viewport *viewports)
 {
 {
-    TRACE("device %p, viewport %p.\n", device, viewport);
-    TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n",
-          viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
+    unsigned int i;
 
 
-    device->update_state->viewport = *viewport;
+    TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports);
+
+    for (i = 0; i < viewport_count; ++i)
+    {
+        TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n",  i, viewports[i].x, viewports[i].y,
+                viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z);
+    }
+
+    if (viewport_count)
+        memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports));
+    else
+        memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports));
+    device->update_state->viewport_count = viewport_count;
 
     /* Handle recording of state blocks */
     if (device->recording)
 
     /* Handle recording of state blocks */
     if (device->recording)
@@ -1944,14 +1958,21 @@ void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const stru
         return;
     }
 
         return;
     }
 
-    wined3d_cs_emit_set_viewport(device->cs, viewport);
+    wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports);
 }
 
 }
 
-void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport)
+void CDECL wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count,
+        struct wined3d_viewport *viewports)
 {
 {
-    TRACE("device %p, viewport %p.\n", device, viewport);
+    unsigned int count;
+
+    TRACE("device %p, viewport_count %p, viewports %p.\n", device, viewport_count, viewports);
 
 
-    *viewport = device->state.viewport;
+    count = viewport_count ? min(*viewport_count, device->state.viewport_count) : 1;
+    if (count && viewports)
+        memcpy(viewports, device->state.viewports, count * sizeof(*viewports));
+    if (viewport_count)
+        *viewport_count = device->state.viewport_count;
 }
 
 static void resolve_depth_buffer(struct wined3d_device *device)
 }
 
 static void resolve_depth_buffer(struct wined3d_device *device)
@@ -2123,19 +2144,33 @@ DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device
     return device->state.sampler_states[sampler_idx][state];
 }
 
     return device->state.sampler_states[sampler_idx][state];
 }
 
-void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect)
+void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsigned int rect_count,
+        const RECT *rects)
 {
 {
-    TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
+    unsigned int i;
+
+    TRACE("device %p, rect_count %u, rects %p.\n", device, rect_count, rects);
+
+    for (i = 0; i < rect_count; ++i)
+    {
+        TRACE("%u: %s\n", i, wine_dbgstr_rect(&rects[i]));
+    }
 
     if (device->recording)
         device->recording->changed.scissorRect = TRUE;
 
 
     if (device->recording)
         device->recording->changed.scissorRect = TRUE;
 
-    if (EqualRect(&device->update_state->scissor_rect, rect))
+    if (device->update_state->scissor_rect_count == rect_count
+            && !memcmp(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects)))
     {
     {
-        TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
+        TRACE("App is setting the old scissor rectangles over, nothing to do.\n");
         return;
     }
         return;
     }
-    CopyRect(&device->update_state->scissor_rect, rect);
+
+    if (rect_count)
+        memcpy(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects));
+    else
+        memset(device->update_state->scissor_rects, 0, sizeof(device->update_state->scissor_rects));
+    device->update_state->scissor_rect_count = rect_count;
 
     if (device->recording)
     {
 
     if (device->recording)
     {
@@ -2143,15 +2178,20 @@ void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const
         return;
     }
 
         return;
     }
 
-    wined3d_cs_emit_set_scissor_rect(device->cs, rect);
+    wined3d_cs_emit_set_scissor_rects(device->cs, rect_count, rects);
 }
 
 }
 
-void CDECL wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect)
+void CDECL wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count, RECT *rects)
 {
 {
-    TRACE("device %p, rect %p.\n", device, rect);
+    unsigned int count;
+
+    TRACE("device %p, rect_count %p, rects %p.\n", device, rect_count, rects);
 
 
-    *rect = device->state.scissor_rect;
-    TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
+    count = rect_count ? min(*rect_count, device->state.scissor_rect_count) : 1;
+    if (count && rects)
+        memcpy(rects, device->state.scissor_rects, count * sizeof(*rects));
+    if (rect_count)
+        *rect_count = device->state.scissor_rect_count;
 }
 
 void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device,
 }
 
 void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device,
@@ -3065,6 +3105,23 @@ struct wined3d_unordered_access_view * CDECL wined3d_device_get_unordered_access
     return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx);
 }
 
     return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx);
 }
 
+void CDECL wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int latency)
+{
+    unsigned int i;
+
+    if (!latency)
+        latency = 3;
+
+    device->max_frame_latency = latency;
+    for (i = 0; i < device->swapchain_count; ++i)
+        swapchain_set_max_frame_latency(device->swapchains[i], device);
+}
+
+unsigned int CDECL wined3d_device_get_max_frame_latency(const struct wined3d_device *device)
+{
+    return device->max_frame_latency;
+}
+
 /* Context activation is done by the caller. */
 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
 /* Context activation is done by the caller. */
 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
@@ -3146,8 +3203,8 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
     TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44);
 
     /* Get the viewport */
     TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44);
 
     /* Get the viewport */
-    wined3d_device_get_viewport(device, &vp);
-    TRACE("viewport  x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
+    wined3d_device_get_viewports(device, NULL, &vp);
+    TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
           vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
 
     multiply_matrix(&mat,&view_mat,&world_mat);
           vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
 
     multiply_matrix(&mat,&view_mat,&world_mat);
@@ -3862,12 +3919,9 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
     level_count = min(src_level_count, dst_level_count);
 
     src_size = max(src_texture->resource.width, src_texture->resource.height);
     level_count = min(src_level_count, dst_level_count);
 
     src_size = max(src_texture->resource.width, src_texture->resource.height);
+    src_size = max(src_size, src_texture->resource.depth);
     dst_size = max(dst_texture->resource.width, dst_texture->resource.height);
     dst_size = max(dst_texture->resource.width, dst_texture->resource.height);
-    if (type == WINED3D_RTYPE_TEXTURE_3D)
-    {
-        src_size = max(src_size, src_texture->resource.depth);
-        dst_size = max(dst_size, dst_texture->resource.depth);
-    }
+    dst_size = max(dst_size, dst_texture->resource.depth);
     while (src_size > dst_size)
     {
         src_size >>= 1;
     while (src_size > dst_size)
     {
         src_size >>= 1;
@@ -4121,14 +4175,17 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device,
 HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device,
         struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
         unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
 HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device,
         struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
         unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
-        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags)
 {
     struct wined3d_box dst_box, b;
 
     TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
 {
     struct wined3d_box dst_box, b;
 
     TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
-            "src_resource %p, src_sub_resource_idx %u, src_box %s.\n",
+            "src_resource %p, src_sub_resource_idx %u, src_box %s, flags %#x.\n",
             device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z,
             device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z,
-            src_resource, src_sub_resource_idx, debug_box(src_box));
+            src_resource, src_sub_resource_idx, debug_box(src_box), flags);
+
+    if (flags)
+        FIXME("Ignoring flags %#x.\n", flags);
 
     if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx)
     {
 
     if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx)
     {
@@ -4193,7 +4250,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
 
         wined3d_box_set(&dst_box, dst_x, 0, dst_x + (src_box->right - src_box->left), 1, 0, 1);
     }
 
         wined3d_box_set(&dst_box, dst_x, 0, dst_x + (src_box->right - src_box->left), 1, 0, 1);
     }
-    else if (dst_resource->type == WINED3D_RTYPE_TEXTURE_2D)
+    else
     {
         struct wined3d_texture *dst_texture = texture_from_resource(dst_resource);
         struct wined3d_texture *src_texture = texture_from_resource(src_resource);
     {
         struct wined3d_texture *dst_texture = texture_from_resource(dst_resource);
         struct wined3d_texture *src_texture = texture_from_resource(src_resource);
@@ -4211,7 +4268,6 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
             return WINED3DERR_INVALIDCALL;
         }
 
             return WINED3DERR_INVALIDCALL;
         }
 
-#if !defined(STAGING_CSMT)
         if (dst_texture->sub_resources[dst_sub_resource_idx].map_count)
         {
             WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx);
         if (dst_texture->sub_resources[dst_sub_resource_idx].map_count)
         {
             WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx);
@@ -4222,33 +4278,22 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
         {
             WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx);
             return WINED3DERR_INVALIDCALL;
         {
             WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx);
             return WINED3DERR_INVALIDCALL;
-#else  /* STAGING_CSMT */
-        if (dst_texture->sub_resources[dst_sub_resource_idx].map_count ||
-            src_texture->sub_resources[src_sub_resource_idx].map_count)
-        {
-            struct wined3d_device *device = dst_texture->resource.device;
-            device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
-            if (dst_texture->sub_resources[dst_sub_resource_idx].map_count ||
-                src_texture->sub_resources[src_sub_resource_idx].map_count)
-            {
-                WARN("Destination or source sub-resource is mapped.\n");
-                return WINEDDERR_SURFACEBUSY;
-            }
-#endif /* STAGING_CSMT */
         }
 
         if (!src_box)
         {
         }
 
         if (!src_box)
         {
-            unsigned int src_w, src_h, dst_w, dst_h, dst_level;
+            unsigned int src_w, src_h, src_d, dst_w, dst_h, dst_d, dst_level;
 
             src_w = wined3d_texture_get_level_width(src_texture, src_level);
             src_h = wined3d_texture_get_level_height(src_texture, src_level);
 
             src_w = wined3d_texture_get_level_width(src_texture, src_level);
             src_h = wined3d_texture_get_level_height(src_texture, src_level);
+            src_d = wined3d_texture_get_level_depth(src_texture, src_level);
 
             dst_level = dst_sub_resource_idx % dst_texture->level_count;
             dst_w = wined3d_texture_get_level_width(dst_texture, dst_level) - dst_x;
             dst_h = wined3d_texture_get_level_height(dst_texture, dst_level) - dst_y;
 
             dst_level = dst_sub_resource_idx % dst_texture->level_count;
             dst_w = wined3d_texture_get_level_width(dst_texture, dst_level) - dst_x;
             dst_h = wined3d_texture_get_level_height(dst_texture, dst_level) - dst_y;
+            dst_d = wined3d_texture_get_level_depth(dst_texture, dst_level) - dst_z;
 
 
-            wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, 1);
+            wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, min(src_d, dst_d));
             src_box = &b;
         }
         else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box)))
             src_box = &b;
         }
         else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box)))
@@ -4258,7 +4303,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
         }
 
         wined3d_box_set(&dst_box, dst_x, dst_y, dst_x + (src_box->right - src_box->left),
         }
 
         wined3d_box_set(&dst_box, dst_x, dst_y, dst_x + (src_box->right - src_box->left),
-                dst_y + (src_box->bottom - src_box->top), 0, 1);
+                dst_y + (src_box->bottom - src_box->top), dst_z, dst_z + (src_box->back - src_box->front));
         if (FAILED(wined3d_texture_check_box_dimensions(dst_texture,
                 dst_sub_resource_idx % dst_texture->level_count, &dst_box)))
         {
         if (FAILED(wined3d_texture_check_box_dimensions(dst_texture,
                 dst_sub_resource_idx % dst_texture->level_count, &dst_box)))
         {
@@ -4266,11 +4311,6 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
             return WINED3DERR_INVALIDCALL;
         }
     }
             return WINED3DERR_INVALIDCALL;
         }
     }
-    else
-    {
-        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type));
-        return WINED3DERR_INVALIDCALL;
-    }
 
     wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box,
             src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT);
 
     wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box,
             src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT);
@@ -4280,13 +4320,17 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev
 
 void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
 
 void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
-        unsigned int depth_pitch)
+        unsigned int depth_pitch, unsigned int flags)
 {
     unsigned int width, height, depth;
     struct wined3d_box b;
 
 {
     unsigned int width, height, depth;
     struct wined3d_box b;
 
-    TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n",
-            device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch);
+    TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u, "
+            "flags %#x.\n",
+            device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch, flags);
+
+    if (flags)
+        FIXME("Ignoring flags %#x.\n", flags);
 
     if (resource->type == WINED3D_RTYPE_BUFFER)
     {
 
     if (resource->type == WINED3D_RTYPE_BUFFER)
     {
@@ -4300,8 +4344,7 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str
         height = 1;
         depth = 1;
     }
         height = 1;
         depth = 1;
     }
-    else if (resource->type == WINED3D_RTYPE_TEXTURE_1D ||
-            resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D)
+    else
     {
         struct wined3d_texture *texture = texture_from_resource(resource);
         unsigned int level;
     {
         struct wined3d_texture *texture = texture_from_resource(resource);
         unsigned int level;
@@ -4317,11 +4360,6 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str
         height = wined3d_texture_get_level_height(texture, level);
         depth = wined3d_texture_get_level_depth(texture, level);
     }
         height = wined3d_texture_get_level_height(texture, level);
         depth = wined3d_texture_get_level_depth(texture, level);
     }
-    else
-    {
-        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
-        return;
-    }
 
     if (!box)
     {
 
     if (!box)
     {
@@ -4336,10 +4374,6 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str
         return;
     }
 
         return;
     }
 
-#if !defined(STAGING_CSMT)
-    wined3d_resource_wait_idle(resource);
-
-#endif /* STAGING_CSMT */
     wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
 }
 
     wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
 }
 
@@ -4403,7 +4437,7 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi
         return WINED3D_OK;
 
     resource = view->resource;
         return WINED3D_OK;
 
     resource = view->resource;
-    if (resource->type != WINED3D_RTYPE_TEXTURE_2D)
+    if (resource->type != WINED3D_RTYPE_TEXTURE_1D && resource->type != WINED3D_RTYPE_TEXTURE_2D)
     {
         FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
         return WINED3DERR_INVALIDCALL;
     {
         FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
         return WINED3DERR_INVALIDCALL;
@@ -4492,19 +4526,20 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device
     {
         struct wined3d_state *state = &device->state;
 
     {
         struct wined3d_state *state = &device->state;
 
-        state->viewport.x = 0;
-        state->viewport.y = 0;
-        state->viewport.width = view->width;
-        state->viewport.height = view->height;
-        state->viewport.min_z = 0.0f;
-        state->viewport.max_z = 1.0f;
-        wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
+        state->viewports[0].x = 0;
+        state->viewports[0].y = 0;
+        state->viewports[0].width = view->width;
+        state->viewports[0].height = view->height;
+        state->viewports[0].min_z = 0.0f;
+        state->viewports[0].max_z = 1.0f;
+        state->viewport_count = 1;
+        wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
 
 
-        SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
-        wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
+        SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height);
+        state->scissor_rect_count = 1;
+        wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects);
     }
 
     }
 
-
     prev = device->fb.render_targets[view_idx];
     if (view == prev)
         return WINED3D_OK;
     prev = device->fb.render_targets[view_idx];
     if (view == prev)
         return WINED3D_OK;
@@ -4836,10 +4871,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc->auto_depth_stencil_format));
     TRACE("flags %#x\n", swapchain_desc->flags);
     TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate);
         TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc->auto_depth_stencil_format));
     TRACE("flags %#x\n", swapchain_desc->flags);
     TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate);
-    TRACE("swap_interval %u\n", swapchain_desc->swap_interval);
     TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode);
 
     TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode);
 
-    if (swapchain_desc->backbuffer_usage != WINED3DUSAGE_RENDERTARGET)
+    if (swapchain_desc->backbuffer_usage && swapchain_desc->backbuffer_usage != WINED3DUSAGE_RENDERTARGET)
         FIXME("Got unexpected backbuffer usage %#x.\n", swapchain_desc->backbuffer_usage);
 
     if (swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_DISCARD
         FIXME("Got unexpected backbuffer usage %#x.\n", swapchain_desc->backbuffer_usage);
 
     if (swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_DISCARD
@@ -4853,7 +4887,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     swapchain->desc.auto_depth_stencil_format = swapchain_desc->auto_depth_stencil_format;
     swapchain->desc.flags = swapchain_desc->flags;
     swapchain->desc.refresh_rate = swapchain_desc->refresh_rate;
     swapchain->desc.auto_depth_stencil_format = swapchain_desc->auto_depth_stencil_format;
     swapchain->desc.flags = swapchain_desc->flags;
     swapchain->desc.refresh_rate = swapchain_desc->refresh_rate;
-    swapchain->desc.swap_interval = swapchain_desc->swap_interval;
     swapchain->desc.auto_restore_display_mode = swapchain_desc->auto_restore_display_mode;
 
     if (swapchain_desc->device_window
     swapchain->desc.auto_restore_display_mode = swapchain_desc->auto_restore_display_mode;
 
     if (swapchain_desc->device_window
@@ -4955,7 +4988,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         wined3d_rendertarget_view_decref(device->back_buffer_view);
         device->back_buffer_view = NULL;
     }
         wined3d_rendertarget_view_decref(device->back_buffer_view);
         device->back_buffer_view = NULL;
     }
-    if (swapchain->desc.backbuffer_count)
+    if (swapchain->desc.backbuffer_count && swapchain->desc.backbuffer_usage & WINED3DUSAGE_RENDERTARGET)
     {
         struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
 
     {
         struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
 
@@ -5006,21 +5039,22 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
 
         /* Note the min_z / max_z is not reset. */
         wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
 
         /* Note the min_z / max_z is not reset. */
-        state->viewport.x = 0;
-        state->viewport.y = 0;
-        state->viewport.width = view->width;
-        state->viewport.height = view->height;
-        wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
+        state->viewports[0].x = 0;
+        state->viewports[0].y = 0;
+        state->viewports[0].width = view->width;
+        state->viewports[0].height = view->height;
+        state->viewport_count = 1;
+        wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
 
 
-        SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
-        wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
+        SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height);
+        state->scissor_rect_count = 1;
+        wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects);
     }
 
     if (device->d3d_initialized)
     {
         if (reset_state)
             hr = wined3d_device_create_primary_opengl_context(device);
     }
 
     if (device->d3d_initialized)
     {
         if (reset_state)
             hr = wined3d_device_create_primary_opengl_context(device);
-        swapchain_update_swap_interval(swapchain);
     }
 
     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
     }
 
     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
@@ -5123,55 +5157,49 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
         case WINED3D_RTYPE_TEXTURE_3D:
             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
             {
         case WINED3D_RTYPE_TEXTURE_3D:
             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
             {
-                struct wined3d_texture *texture = texture_from_resource(resource);
-
-                if (device->state.textures[i] == texture)
+                if (&device->state.textures[i]->resource == resource)
                 {
                 {
-                    ERR("Texture %p is still in use, stage %u.\n", texture, i);
+                    ERR("Texture resource %p is still in use, stage %u.\n", resource, i);
                     device->state.textures[i] = NULL;
                 }
 
                     device->state.textures[i] = NULL;
                 }
 
-                if (device->recording && device->update_state->textures[i] == texture)
+                if (device->recording && &device->update_state->textures[i]->resource == resource)
                 {
                 {
-                    ERR("Texture %p is still in use by recording stateblock %p, stage %u.\n",
-                            texture, device->recording, i);
+                    ERR("Texture resource %p is still in use by recording stateblock %p, stage %u.\n",
+                            resource, device->recording, i);
                     device->update_state->textures[i] = NULL;
                 }
             }
             break;
 
         case WINED3D_RTYPE_BUFFER:
                     device->update_state->textures[i] = NULL;
                 }
             }
             break;
 
         case WINED3D_RTYPE_BUFFER:
+            for (i = 0; i < MAX_STREAMS; ++i)
             {
             {
-                struct wined3d_buffer *buffer = buffer_from_resource(resource);
-
-                for (i = 0; i < MAX_STREAMS; ++i)
+                if (&device->state.streams[i].buffer->resource == resource)
                 {
                 {
-                    if (device->state.streams[i].buffer == buffer)
-                    {
-                        ERR("Buffer %p is still in use, stream %u.\n", buffer, i);
-                        device->state.streams[i].buffer = NULL;
-                    }
-
-                    if (device->recording && device->update_state->streams[i].buffer == buffer)
-                    {
-                        ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
-                                buffer, device->recording, i);
-                        device->update_state->streams[i].buffer = NULL;
-                    }
+                    ERR("Buffer resource %p is still in use, stream %u.\n", resource, i);
+                    device->state.streams[i].buffer = NULL;
                 }
 
                 }
 
-                if (device->state.index_buffer == buffer)
+                if (device->recording && &device->update_state->streams[i].buffer->resource == resource)
                 {
                 {
-                    ERR("Buffer %p is still in use as index buffer.\n", buffer);
-                    device->state.index_buffer =  NULL;
+                    ERR("Buffer resource %p is still in use by stateblock %p, stream %u.\n",
+                            resource, device->recording, i);
+                    device->update_state->streams[i].buffer = NULL;
                 }
                 }
+            }
 
 
-                if (device->recording && device->update_state->index_buffer == buffer)
-                {
-                    ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
-                            buffer, device->recording);
-                    device->update_state->index_buffer =  NULL;
-                }
+            if (&device->state.index_buffer->resource == resource)
+            {
+                ERR("Buffer resource %p is still in use as index buffer.\n", resource);
+                device->state.index_buffer =  NULL;
+            }
+
+            if (device->recording && &device->update_state->index_buffer->resource == resource)
+            {
+                ERR("Buffer resource %p is still in use by stateblock %p as index buffer.\n",
+                        resource, device->recording);
+                device->update_state->index_buffer =  NULL;
             }
             break;
 
             }
             break;
 
@@ -5240,6 +5268,8 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
             &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT);
     device->update_state = &device->state;
 
             &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT);
     device->update_state = &device->state;
 
+    device->max_frame_latency = 3;
+
     if (!(device->cs = wined3d_cs_create(device)))
     {
         WARN("Failed to create command stream.\n");
     if (!(device->cs = wined3d_cs_create(device)))
     {
         WARN("Failed to create command stream.\n");
@@ -5339,58 +5369,3 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
     else
         return CallWindowProcA(proc, window, message, wparam, lparam);
 }
     else
         return CallWindowProcA(proc, window, message, wparam, lparam);
 }
-#if defined(STAGING_CSMT)
-
-/* Context activation is done by the caller */
-struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage,
-        GLenum type_hint, struct wined3d_context *context)
-{
-    struct wined3d_gl_bo *ret;
-    const struct wined3d_gl_info *gl_info;
-
-    TRACE("device %p, size %u, gl_usage %u, type_hint %u\n", device, size, gl_usage,
-            type_hint);
-
-    ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
-    if(!ret)
-        return NULL;
-    ret->type_hint = type_hint;
-    ret->size = size;
-    ret->usage = gl_usage;
-
-    gl_info = context->gl_info;
-
-    GL_EXTCALL(glGenBuffers(1, &ret->name));
-    if (type_hint == GL_ELEMENT_ARRAY_BUFFER)
-        context_invalidate_state(context, STATE_INDEXBUFFER);
-    GL_EXTCALL(glBindBuffer(type_hint, ret->name));
-    GL_EXTCALL(glBufferData(type_hint, size, NULL, gl_usage));
-    GL_EXTCALL(glBindBuffer(type_hint, 0));
-    checkGLcall("Create buffer object");
-
-    TRACE("Successfully created and set up buffer %u\n", ret->name);
-    return ret;
-}
-
-/* Context activation is done by the caller */
-static void wined3d_device_destroy_bo(struct wined3d_device *device, const struct wined3d_context *context,
-        struct wined3d_gl_bo *bo)
-{
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name);
-
-    GL_EXTCALL(glDeleteBuffers(1, &bo->name));
-    checkGLcall("glDeleteBuffers");
-
-    HeapFree(GetProcessHeap(), 0, bo);
-}
-
-/* Context activation is done by the caller */
-void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo,
-        const struct wined3d_context *context)
-{
-    TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name);
-
-    wined3d_device_destroy_bo(device, context, bo);
-}
-#endif /* STAGING_CSMT */
index d82a671..baeb287 100644 (file)
@@ -156,6 +156,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_point_parameters",             ARB_POINT_PARAMETERS          },
     {"GL_ARB_point_sprite",                 ARB_POINT_SPRITE              },
     {"GL_ARB_provoking_vertex",             ARB_PROVOKING_VERTEX          },
     {"GL_ARB_point_parameters",             ARB_POINT_PARAMETERS          },
     {"GL_ARB_point_sprite",                 ARB_POINT_SPRITE              },
     {"GL_ARB_provoking_vertex",             ARB_PROVOKING_VERTEX          },
+    {"GL_ARB_sample_shading",               ARB_SAMPLE_SHADING            },
     {"GL_ARB_sampler_objects",              ARB_SAMPLER_OBJECTS           },
     {"GL_ARB_seamless_cube_map",            ARB_SEAMLESS_CUBE_MAP         },
     {"GL_ARB_shader_atomic_counters",       ARB_SHADER_ATOMIC_COUNTERS    },
     {"GL_ARB_sampler_objects",              ARB_SAMPLER_OBJECTS           },
     {"GL_ARB_seamless_cube_map",            ARB_SEAMLESS_CUBE_MAP         },
     {"GL_ARB_shader_atomic_counters",       ARB_SHADER_ATOMIC_COUNTERS    },
@@ -163,6 +164,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_shader_image_load_store",      ARB_SHADER_IMAGE_LOAD_STORE   },
     {"GL_ARB_shader_image_size",            ARB_SHADER_IMAGE_SIZE         },
     {"GL_ARB_shader_storage_buffer_object", ARB_SHADER_STORAGE_BUFFER_OBJECT},
     {"GL_ARB_shader_image_load_store",      ARB_SHADER_IMAGE_LOAD_STORE   },
     {"GL_ARB_shader_image_size",            ARB_SHADER_IMAGE_SIZE         },
     {"GL_ARB_shader_storage_buffer_object", ARB_SHADER_STORAGE_BUFFER_OBJECT},
+    {"GL_ARB_shader_texture_image_samples", ARB_SHADER_TEXTURE_IMAGE_SAMPLES},
     {"GL_ARB_shader_texture_lod",           ARB_SHADER_TEXTURE_LOD        },
     {"GL_ARB_shading_language_100",         ARB_SHADING_LANGUAGE_100      },
     {"GL_ARB_shading_language_420pack",     ARB_SHADING_LANGUAGE_420PACK  },
     {"GL_ARB_shader_texture_lod",           ARB_SHADER_TEXTURE_LOD        },
     {"GL_ARB_shading_language_100",         ARB_SHADING_LANGUAGE_100      },
     {"GL_ARB_shading_language_420pack",     ARB_SHADING_LANGUAGE_420PACK  },
@@ -201,7 +203,6 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_transform_feedback3",          ARB_TRANSFORM_FEEDBACK3       },
     {"GL_ARB_uniform_buffer_object",        ARB_UNIFORM_BUFFER_OBJECT     },
     {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA         },
     {"GL_ARB_transform_feedback3",          ARB_TRANSFORM_FEEDBACK3       },
     {"GL_ARB_uniform_buffer_object",        ARB_UNIFORM_BUFFER_OBJECT     },
     {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA         },
-    {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND              },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT      },
     {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM            },
     {"GL_ARB_vertex_shader",                ARB_VERTEX_SHADER             },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT      },
     {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM            },
     {"GL_ARB_vertex_shader",                ARB_VERTEX_SHADER             },
@@ -678,7 +679,7 @@ static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, struc
     GLenum error;
     DWORD data[16];
 
     GLenum error;
     DWORD data[16];
 
-    if (!gl_info->supported[EXT_SECONDARY_COLOR])
+    if (!gl_info->supported[EXT_SECONDARY_COLOR] || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
         return FALSE;
 
     while (gl_info->gl_ops.gl.p_glGetError());
         return FALSE;
 
     while (gl_info->gl_ops.gl.p_glGetError());
@@ -858,6 +859,8 @@ static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, struct w
         return FALSE;
     if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
         return FALSE;
         return FALSE;
     if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
         return FALSE;
+    if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+        return FALSE;
 
     gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
     gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
 
     gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
     gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
@@ -1398,11 +1401,13 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980,     "NVIDIA GeForce GTX 980",           DRIVER_NVIDIA_GEFORCE8,  4096},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980TI,   "NVIDIA GeForce GTX 980 Ti",        DRIVER_NVIDIA_GEFORCE8,  6144},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1050,    "NVIDIA GeForce GTX 1050",          DRIVER_NVIDIA_GEFORCE8,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980,     "NVIDIA GeForce GTX 980",           DRIVER_NVIDIA_GEFORCE8,  4096},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980TI,   "NVIDIA GeForce GTX 980 Ti",        DRIVER_NVIDIA_GEFORCE8,  6144},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1050,    "NVIDIA GeForce GTX 1050",          DRIVER_NVIDIA_GEFORCE8,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1050TI,  "NVIDIA GeForce GTX 1050 Ti",       DRIVER_NVIDIA_GEFORCE8,  4096},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1060,    "NVIDIA GeForce GTX 1060",          DRIVER_NVIDIA_GEFORCE8,  6144},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1070,    "NVIDIA GeForce GTX 1070",          DRIVER_NVIDIA_GEFORCE8,  8192},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080,    "NVIDIA GeForce GTX 1080",          DRIVER_NVIDIA_GEFORCE8,  8192},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080TI,  "NVIDIA GeForce GTX 1080 Ti",       DRIVER_NVIDIA_GEFORCE8,  11264},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_TITANX_PASCAL,      "NVIDIA TITAN X (Pascal)",          DRIVER_NVIDIA_GEFORCE8,  12288},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1060,    "NVIDIA GeForce GTX 1060",          DRIVER_NVIDIA_GEFORCE8,  6144},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1070,    "NVIDIA GeForce GTX 1070",          DRIVER_NVIDIA_GEFORCE8,  8192},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080,    "NVIDIA GeForce GTX 1080",          DRIVER_NVIDIA_GEFORCE8,  8192},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080TI,  "NVIDIA GeForce GTX 1080 Ti",       DRIVER_NVIDIA_GEFORCE8,  11264},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_TITANX_PASCAL,      "NVIDIA TITAN X (Pascal)",          DRIVER_NVIDIA_GEFORCE8,  12288},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_TITANV,             "NVIDIA TITAN V",                   DRIVER_NVIDIA_GEFORCE8,  12288},
 
     /* AMD cards */
     {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
 
     /* AMD cards */
     {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
@@ -1703,13 +1708,11 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
      * In order to avoid this application bug we limit the amount of video memory
      * to LONG_MAX for older Windows versions.
      */
      * In order to avoid this application bug we limit the amount of video memory
      * to LONG_MAX for older Windows versions.
      */
-#ifdef __i386__
     if (driver_model < DRIVER_MODEL_NT6X && driver_info->vram_bytes > LONG_MAX)
     {
         TRACE("Limiting amount of video memory to %#lx bytes for OS version older than Vista.\n", LONG_MAX);
         driver_info->vram_bytes = LONG_MAX;
     }
     if (driver_model < DRIVER_MODEL_NT6X && driver_info->vram_bytes > LONG_MAX)
     {
         TRACE("Limiting amount of video memory to %#lx bytes for OS version older than Vista.\n", LONG_MAX);
         driver_info->vram_bytes = LONG_MAX;
     }
-#endif
 
     /* Try to obtain driver version information for the current Windows version. This fails in
      * some cases:
 
     /* Try to obtain driver version information for the current Windows version. This fails in
      * some cases:
@@ -1903,11 +1906,13 @@ static const struct wined3d_renderer_table
 cards_nvidia_binary[] =
 {
     /* Direct 3D 11 */
 cards_nvidia_binary[] =
 {
     /* Direct 3D 11 */
+    {"TITAN V",                     CARD_NVIDIA_TITANV},            /* GeForce 1000 - highend */
     {"TITAN X (Pascal)",            CARD_NVIDIA_TITANX_PASCAL},     /* GeForce 1000 - highend */
     {"GTX 1080 Ti",                 CARD_NVIDIA_GEFORCE_GTX1080TI}, /* GeForce 1000 - highend */
     {"GTX 1080",                    CARD_NVIDIA_GEFORCE_GTX1080},   /* GeForce 1000 - highend */
     {"GTX 1070",                    CARD_NVIDIA_GEFORCE_GTX1070},   /* GeForce 1000 - highend */
     {"GTX 1060",                    CARD_NVIDIA_GEFORCE_GTX1060},   /* GeForce 1000 - midend high */
     {"TITAN X (Pascal)",            CARD_NVIDIA_TITANX_PASCAL},     /* GeForce 1000 - highend */
     {"GTX 1080 Ti",                 CARD_NVIDIA_GEFORCE_GTX1080TI}, /* GeForce 1000 - highend */
     {"GTX 1080",                    CARD_NVIDIA_GEFORCE_GTX1080},   /* GeForce 1000 - highend */
     {"GTX 1070",                    CARD_NVIDIA_GEFORCE_GTX1070},   /* GeForce 1000 - highend */
     {"GTX 1060",                    CARD_NVIDIA_GEFORCE_GTX1060},   /* GeForce 1000 - midend high */
+    {"GTX 1050 Ti",                 CARD_NVIDIA_GEFORCE_GTX1050TI}, /* GeForce 1000 - midend */
     {"GTX 1050",                    CARD_NVIDIA_GEFORCE_GTX1050},   /* GeForce 1000 - midend */
     {"GTX 980 Ti",                  CARD_NVIDIA_GEFORCE_GTX980TI},  /* GeForce 900 - highend */
     {"GTX 980",                     CARD_NVIDIA_GEFORCE_GTX980},    /* GeForce 900 - highend */
     {"GTX 1050",                    CARD_NVIDIA_GEFORCE_GTX1050},   /* GeForce 1000 - midend */
     {"GTX 980 Ti",                  CARD_NVIDIA_GEFORCE_GTX980TI},  /* GeForce 900 - highend */
     {"GTX 980",                     CARD_NVIDIA_GEFORCE_GTX980},    /* GeForce 900 - highend */
@@ -2225,9 +2230,7 @@ cards_intel[] =
     {"830M",                        CARD_INTEL_830M},
 },
 /* 20101109 - These are never returned by current Gallium radeon
     {"830M",                        CARD_INTEL_830M},
 },
 /* 20101109 - These are never returned by current Gallium radeon
- * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351.
- *
- * These are returned but not handled: RC410, RV380. */
+ * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351. */
 cards_amd_mesa[] =
 {
     /* Polaris 10/11 */
 cards_amd_mesa[] =
 {
     /* Polaris 10/11 */
@@ -2305,10 +2308,12 @@ cards_amd_mesa[] =
     {"RS482",                       CARD_AMD_RADEON_XPRESS_200M},
     {"RS480",                       CARD_AMD_RADEON_XPRESS_200M},
     {"RS400",                       CARD_AMD_RADEON_XPRESS_200M},
     {"RS482",                       CARD_AMD_RADEON_XPRESS_200M},
     {"RS480",                       CARD_AMD_RADEON_XPRESS_200M},
     {"RS400",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RC410",                       CARD_AMD_RADEON_XPRESS_200M},
     /* R300 */
     {"R360",                        CARD_AMD_RADEON_9500},
     {"R350",                        CARD_AMD_RADEON_9500},
     {"R300",                        CARD_AMD_RADEON_9500},
     /* R300 */
     {"R360",                        CARD_AMD_RADEON_9500},
     {"R350",                        CARD_AMD_RADEON_9500},
     {"R300",                        CARD_AMD_RADEON_9500},
+    {"RV380",                       CARD_AMD_RADEON_9500},
     {"RV370",                       CARD_AMD_RADEON_9500},
     {"RV360",                       CARD_AMD_RADEON_9500},
     {"RV351",                       CARD_AMD_RADEON_9500},
     {"RV370",                       CARD_AMD_RADEON_9500},
     {"RV360",                       CARD_AMD_RADEON_9500},
     {"RV351",                       CARD_AMD_RADEON_9500},
@@ -2822,6 +2827,8 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glPointParameterfvARB)
     /* GL_ARB_provoking_vertex */
     USE_GL_FUNC(glProvokingVertex)
     USE_GL_FUNC(glPointParameterfvARB)
     /* GL_ARB_provoking_vertex */
     USE_GL_FUNC(glProvokingVertex)
+    /* GL_ARB_sample_shading */
+    USE_GL_FUNC(glMinSampleShadingARB)
     /* GL_ARB_sampler_objects */
     USE_GL_FUNC(glGenSamplers)
     USE_GL_FUNC(glDeleteSamplers)
     /* GL_ARB_sampler_objects */
     USE_GL_FUNC(glGenSamplers)
     USE_GL_FUNC(glDeleteSamplers)
@@ -2948,17 +2955,6 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glGetUniformBlockIndex)
     USE_GL_FUNC(glGetUniformIndices)
     USE_GL_FUNC(glUniformBlockBinding)
     USE_GL_FUNC(glGetUniformBlockIndex)
     USE_GL_FUNC(glGetUniformIndices)
     USE_GL_FUNC(glUniformBlockBinding)
-    /* GL_ARB_vertex_blend */
-    USE_GL_FUNC(glVertexBlendARB)
-    USE_GL_FUNC(glWeightPointerARB)
-    USE_GL_FUNC(glWeightbvARB)
-    USE_GL_FUNC(glWeightdvARB)
-    USE_GL_FUNC(glWeightfvARB)
-    USE_GL_FUNC(glWeightivARB)
-    USE_GL_FUNC(glWeightsvARB)
-    USE_GL_FUNC(glWeightubvARB)
-    USE_GL_FUNC(glWeightuivARB)
-    USE_GL_FUNC(glWeightusvARB)
     /* GL_ARB_vertex_buffer_object */
     USE_GL_FUNC(glBindBufferARB)
     USE_GL_FUNC(glBufferDataARB)
     /* GL_ARB_vertex_buffer_object */
     USE_GL_FUNC(glBindBufferARB)
     USE_GL_FUNC(glBufferDataARB)
@@ -3426,6 +3422,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     MAP_GL_FUNCTION(glIsEnabledi, glIsEnabledIndexedEXT);
     MAP_GL_FUNCTION(glLinkProgram, glLinkProgramARB);
     MAP_GL_FUNCTION(glMapBuffer, glMapBufferARB);
     MAP_GL_FUNCTION(glIsEnabledi, glIsEnabledIndexedEXT);
     MAP_GL_FUNCTION(glLinkProgram, glLinkProgramARB);
     MAP_GL_FUNCTION(glMapBuffer, glMapBufferARB);
+    MAP_GL_FUNCTION(glMinSampleShading, glMinSampleShadingARB);
     MAP_GL_FUNCTION_CAST(glShaderSource, glShaderSourceARB);
     MAP_GL_FUNCTION(glTexBuffer, glTexBufferARB);
     MAP_GL_FUNCTION_CAST(glTexImage3D, glTexImage3DEXT);
     MAP_GL_FUNCTION_CAST(glShaderSource, glShaderSourceARB);
     MAP_GL_FUNCTION(glTexBuffer, glTexBufferARB);
     MAP_GL_FUNCTION_CAST(glTexImage3D, glTexImage3DEXT);
@@ -3479,7 +3476,6 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
     GLfloat gl_floatv[2];
     GLint gl_max;
 
     GLfloat gl_floatv[2];
     GLint gl_max;
 
-    gl_info->limits.blends = 1;
     gl_info->limits.buffers = 1;
     gl_info->limits.textures = 0;
     gl_info->limits.texture_coords = 0;
     gl_info->limits.buffers = 1;
     gl_info->limits.textures = 0;
     gl_info->limits.texture_coords = 0;
@@ -3635,12 +3631,6 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
         gl_info->limits.texture_coords = 1;
     }
 
         gl_info->limits.texture_coords = 1;
     }
 
-    if (gl_info->supported[ARB_VERTEX_BLEND])
-    {
-        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
-        gl_info->limits.blends = gl_max;
-        TRACE("Max blends: %u.\n", gl_info->limits.blends);
-    }
     if (gl_info->supported[EXT_TEXTURE3D])
     {
         gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
     if (gl_info->supported[EXT_TEXTURE3D])
     {
         gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
@@ -3910,6 +3900,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
         {EXT_TEXTURE_SNORM,                MAKEDWORD_VERSION(3, 1)},
         /* We don't need or want GL_ARB_texture_rectangle (core in 3.1). */
 
         {EXT_TEXTURE_SNORM,                MAKEDWORD_VERSION(3, 1)},
         /* We don't need or want GL_ARB_texture_rectangle (core in 3.1). */
 
+        {ARB_DEPTH_CLAMP,                  MAKEDWORD_VERSION(3, 2)},
         {ARB_DRAW_ELEMENTS_BASE_VERTEX,    MAKEDWORD_VERSION(3, 2)},
         /* ARB_geometry_shader4 exposes a somewhat different API compared to 3.2
          * core geometry shaders so it's not really correct to expose the
         {ARB_DRAW_ELEMENTS_BASE_VERTEX,    MAKEDWORD_VERSION(3, 2)},
         /* ARB_geometry_shader4 exposes a somewhat different API compared to 3.2
          * core geometry shaders so it's not really correct to expose the
@@ -3933,6 +3924,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
 
         {ARB_DRAW_INDIRECT,                MAKEDWORD_VERSION(4, 0)},
         {ARB_GPU_SHADER5,                  MAKEDWORD_VERSION(4, 0)},
 
         {ARB_DRAW_INDIRECT,                MAKEDWORD_VERSION(4, 0)},
         {ARB_GPU_SHADER5,                  MAKEDWORD_VERSION(4, 0)},
+        {ARB_SAMPLE_SHADING,               MAKEDWORD_VERSION(4, 0)},
         {ARB_TESSELLATION_SHADER,          MAKEDWORD_VERSION(4, 0)},
         {ARB_TEXTURE_CUBE_MAP_ARRAY,       MAKEDWORD_VERSION(4, 0)},
         {ARB_TEXTURE_GATHER,               MAKEDWORD_VERSION(4, 0)},
         {ARB_TESSELLATION_SHADER,          MAKEDWORD_VERSION(4, 0)},
         {ARB_TEXTURE_CUBE_MAP_ARRAY,       MAKEDWORD_VERSION(4, 0)},
         {ARB_TEXTURE_GATHER,               MAKEDWORD_VERSION(4, 0)},
@@ -3974,6 +3966,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
         {ARB_CLIP_CONTROL,                 MAKEDWORD_VERSION(4, 5)},
         {ARB_CULL_DISTANCE,                MAKEDWORD_VERSION(4, 5)},
         {ARB_DERIVATIVE_CONTROL,           MAKEDWORD_VERSION(4, 5)},
         {ARB_CLIP_CONTROL,                 MAKEDWORD_VERSION(4, 5)},
         {ARB_CULL_DISTANCE,                MAKEDWORD_VERSION(4, 5)},
         {ARB_DERIVATIVE_CONTROL,           MAKEDWORD_VERSION(4, 5)},
+        {ARB_SHADER_TEXTURE_IMAGE_SAMPLES, MAKEDWORD_VERSION(4, 5)},
 
         {ARB_PIPELINE_STATISTICS_QUERY,    MAKEDWORD_VERSION(4, 6)},
         {ARB_TEXTURE_FILTER_ANISOTROPIC,   MAKEDWORD_VERSION(4, 6)},
 
         {ARB_PIPELINE_STATISTICS_QUERY,    MAKEDWORD_VERSION(4, 6)},
         {ARB_TEXTURE_FILTER_ANISOTROPIC,   MAKEDWORD_VERSION(4, 6)},
@@ -4087,7 +4080,11 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
         gl_info->supported[WINED3D_GL_BLEND_EQUATION] = TRUE;
 
     if (gl_version >= MAKEDWORD_VERSION(2, 0))
         gl_info->supported[WINED3D_GL_BLEND_EQUATION] = TRUE;
 
     if (gl_version >= MAKEDWORD_VERSION(2, 0))
+    {
         gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE;
         gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE;
+        /* We want to use the core APIs for two-sided stencil in GL 2.0. */
+        gl_info->supported[EXT_STENCIL_TWO_SIDE] = FALSE;
+    }
     if (gl_version >= MAKEDWORD_VERSION(3, 2))
         gl_info->supported[WINED3D_GL_VERSION_3_2] = TRUE;
 
     if (gl_version >= MAKEDWORD_VERSION(3, 2))
         gl_info->supported[WINED3D_GL_VERSION_3_2] = TRUE;
 
@@ -5360,7 +5357,7 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
         case WINED3D_RTYPE_NONE:
             allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
                     | WINED3DUSAGE_RENDERTARGET;
         case WINED3D_RTYPE_NONE:
             allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
                     | WINED3DUSAGE_RENDERTARGET;
-            gl_type = WINED3D_GL_RES_TYPE_TEX_1D;
+            gl_type = WINED3D_GL_RES_TYPE_TEX_2D;
             gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
             break;
 
             gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
             break;
 
@@ -5369,6 +5366,7 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
                     | WINED3DUSAGE_SOFTWAREPROCESSING
                     | WINED3DUSAGE_TEXTURE
                     | WINED3DUSAGE_QUERY_FILTER
                     | WINED3DUSAGE_SOFTWAREPROCESSING
                     | WINED3DUSAGE_TEXTURE
                     | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_GENMIPMAP
                     | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
                     | WINED3DUSAGE_QUERY_SRGBREAD
                     | WINED3DUSAGE_QUERY_SRGBWRITE
                     | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
                     | WINED3DUSAGE_QUERY_SRGBREAD
                     | WINED3DUSAGE_QUERY_SRGBWRITE
@@ -5433,12 +5431,6 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
             gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
             break;
 
             gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
             break;
 
-        case WINED3D_RTYPE_BUFFER:
-            allowed_usage = WINED3DUSAGE_DYNAMIC
-                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            gl_type = gl_type_end = WINED3D_GL_RES_TYPE_BUFFER;
-            break;
-
         default:
             FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
             return WINED3DERR_NOTAVAILABLE;
         default:
             FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
             return WINED3DERR_NOTAVAILABLE;
@@ -5687,9 +5679,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                      WINED3DCAPS3_COPY_TO_VIDMEM                   |
                                      WINED3DCAPS3_COPY_TO_SYSTEMMEM;
 
                                      WINED3DCAPS3_COPY_TO_VIDMEM                   |
                                      WINED3DCAPS3_COPY_TO_SYSTEMMEM;
 
-    caps->PresentationIntervals    = WINED3DPRESENT_INTERVAL_IMMEDIATE  |
-                                     WINED3DPRESENT_INTERVAL_ONE;
-
     caps->CursorCaps               = WINED3DCURSORCAPS_COLOR            |
                                      WINED3DCURSORCAPS_LOWRES;
 
     caps->CursorCaps               = WINED3DCURSORCAPS_COLOR            |
                                      WINED3DCURSORCAPS_LOWRES;
 
@@ -6619,28 +6608,16 @@ static DWORD get_max_gl_version(const struct wined3d_gl_info *gl_info, DWORD fla
 {
     const char *gl_vendor, *gl_renderer;
 
 {
     const char *gl_vendor, *gl_renderer;
 
-    if (wined3d_settings.explicit_gl_version || (flags & WINED3D_PIXEL_CENTER_INTEGER))
+    if (wined3d_settings.explicit_gl_version)
         return wined3d_settings.max_gl_version;
 
     gl_vendor = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_VENDOR);
     gl_renderer = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_RENDERER);
     if (!gl_vendor || !gl_renderer
             || wined3d_guess_card_vendor(gl_vendor, gl_renderer) == HW_VENDOR_NVIDIA)
         return wined3d_settings.max_gl_version;
 
     gl_vendor = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_VENDOR);
     gl_renderer = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_RENDERER);
     if (!gl_vendor || !gl_renderer
             || wined3d_guess_card_vendor(gl_vendor, gl_renderer) == HW_VENDOR_NVIDIA)
-        return wined3d_settings.max_gl_version;
+        return MAKEDWORD_VERSION(1, 0);
 
 
-    return MAKEDWORD_VERSION(4, 4);
-}
-
-static BOOL has_extension(const char *list, const char *ext)
-{
-    size_t len = strlen(ext);
-    while (list)
-    {
-        while (*list == ' ') list++;
-        if (!strncmp(list, ext, len) && (!list[len] || list[len] == ' ')) return TRUE;
-        list = strchr(list, ' ');
-    }
-    return FALSE;
+    return wined3d_settings.max_gl_version;
 }
 
 static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, DWORD wined3d_creation_flags)
 }
 
 static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, DWORD wined3d_creation_flags)
@@ -6701,17 +6678,6 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal,
     }
 
     max_gl_version = get_max_gl_version(gl_info, wined3d_creation_flags);
     }
 
     max_gl_version = get_max_gl_version(gl_info, wined3d_creation_flags);
-
-    if (wined3d_creation_flags & WINED3D_REQUEST_D3D10)
-    {
-        const char *gl_extensions = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_EXTENSIONS);
-        if (!has_extension(gl_extensions, "GL_ARB_compatibility"))
-        {
-            ERR_(winediag)("GL_ARB_compatibility not supported, requesting context with GL version 3.2.\n");
-            max_gl_version = MAKEDWORD_VERSION(3, 2);
-        }
-    }
-
     for (i = 0; i < ARRAY_SIZE(supported_gl_versions); ++i)
     {
         if (supported_gl_versions[i] <= max_gl_version)
     for (i = 0; i < ARRAY_SIZE(supported_gl_versions); ++i)
     {
         if (supported_gl_versions[i] <= max_gl_version)
index 4c879f9..41bd1fd 100644 (file)
@@ -91,7 +91,6 @@ struct glsl_sample_function
     enum wined3d_data_type data_type;
     BOOL output_single_component;
     unsigned int offset_size;
     enum wined3d_data_type data_type;
     BOOL output_single_component;
     unsigned int offset_size;
-    enum wined3d_shader_resource_type emulate_lod;
 };
 
 enum heap_node_op
 };
 
 enum heap_node_op
@@ -805,11 +804,12 @@ static void append_transform_feedback_skip_components(const char **varyings,
     }
 }
 
     }
 }
 
-static void shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc,
+static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc,
         struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
         char *strings, unsigned int *strings_length, GLenum buffer_mode)
 {
     unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
         struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
         char *strings, unsigned int *strings_length, GLenum buffer_mode)
 {
     unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
+    BOOL have_varyings_to_record = FALSE;
 
     count = length = 0;
     highest_output_slot = 0;
 
     count = length = 0;
     highest_output_slot = 0;
@@ -859,6 +859,8 @@ static void shader_glsl_generate_transform_feedback_varyings(const struct wined3
                 string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx);
                 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
             }
                 string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx);
                 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
             }
+
+            have_varyings_to_record = TRUE;
         }
 
         if (buffer_idx < so_desc->buffer_stride_count
         }
 
         if (buffer_idx < so_desc->buffer_stride_count
@@ -883,10 +885,12 @@ static void shader_glsl_generate_transform_feedback_varyings(const struct wined3
         *varying_count = count;
     if (strings_length)
         *strings_length = length;
         *varying_count = count;
     if (strings_length)
         *strings_length = length;
+
+    return have_varyings_to_record;
 }
 
 static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
 }
 
 static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
-        struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader)
+        struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
 {
     const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
     const struct wined3d_gl_info *gl_info = context->gl_info;
 {
     const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -942,7 +946,13 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
 
     buffer = string_buffer_get(&priv->string_buffers);
 
 
     buffer = string_buffer_get(&priv->string_buffers);
 
-    shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode);
+    if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode))
+    {
+        FIXME("No varyings to record, disabling transform feedback.\n");
+        shader->u.gs.so_desc.element_count = 0;
+        string_buffer_release(&priv->string_buffers, buffer);
+        return;
+    }
 
     if (!(varyings = heap_calloc(count, sizeof(*varyings))))
     {
 
     if (!(varyings = heap_calloc(count, sizeof(*varyings))))
     {
@@ -1460,7 +1470,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
     const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct shader_glsl_priv *priv = shader_priv;
     const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct shader_glsl_priv *priv = shader_priv;
-    float position_fixup[4];
+    float position_fixup[4 * WINED3D_MAX_VIEWPORTS];
     float normal[3 * 3];
     DWORD update_mask;
 
     float normal[3 * 3];
     DWORD update_mask;
 
@@ -1498,9 +1508,11 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
 
     if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP)
     {
 
     if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP)
     {
-        shader_get_position_fixup(context, state, position_fixup);
+        unsigned int fixup_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ?
+                max(state->viewport_count, 1) : 1;
+        shader_get_position_fixup(context, state, fixup_count, position_fixup);
         if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
         if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
-            GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup));
+            GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, fixup_count, position_fixup));
         else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
             GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup));
         else
         else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
             GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup));
         else
@@ -1957,6 +1969,11 @@ static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_
     }
 }
 
     }
 }
 
+static const char *get_fragment_output(const struct wined3d_gl_info *gl_info)
+{
+    return needs_legacy_glsl_syntax(gl_info) ? "gl_FragData" : "ps_out";
+}
+
 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
 {
     switch (primitive_type)
 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
 {
     switch (primitive_type)
@@ -2939,6 +2956,10 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
                 sprintf(register_name, "vpc[%u]", reg->idx[0].offset);
             break;
 
                 sprintf(register_name, "vpc[%u]", reg->idx[0].offset);
             break;
 
+        case WINED3DSPR_SAMPLEMASK:
+            sprintf(register_name, "sample_mask");
+            break;
+
         default:
             FIXME("Unhandled register type %#x.\n", reg->type);
             sprintf(register_name, "unrecognized_register");
         default:
             FIXME("Unhandled register type %#x.\n", reg->type);
             sprintf(register_name, "unrecognized_register");
@@ -3243,7 +3264,6 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type;
     struct shader_glsl_ctx_priv *priv = ctx->backend_data;
     const struct wined3d_gl_info *gl_info = ctx->gl_info;
     enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type;
     struct shader_glsl_ctx_priv *priv = ctx->backend_data;
     const struct wined3d_gl_info *gl_info = ctx->gl_info;
-    BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info);
     BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx);
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
     BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
     BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx);
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
     BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
@@ -3256,7 +3276,6 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     unsigned int coord_size, deriv_size;
 
     sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type;
     unsigned int coord_size, deriv_size;
 
     sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type;
-    sample_function->emulate_lod = WINED3D_SHADER_RESOURCE_NONE;
 
     if (resource_type >= ARRAY_SIZE(resource_type_info))
     {
 
     if (resource_type >= ARRAY_SIZE(resource_type_info))
     {
@@ -3268,30 +3287,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
         projected = FALSE;
 
     if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
         projected = FALSE;
 
-    if (shadow && lod)
-    {
-        switch (resource_type)
-        {
-            /* emulate textureLod(sampler2DArrayShadow, ...) using textureGradOffset */
-            case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
-                sample_function->emulate_lod = resource_type;
-                grad = offset = TRUE;
-                lod = FALSE;
-                break;
-
-            /* emulate textureLod(samplerCubeShadow, ...) using shadowCubeGrad */
-            case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
-                sample_function->emulate_lod = resource_type;
-                grad = legacy_syntax = TRUE;
-                lod = FALSE;
-                break;
-
-            default:
-                break;
-        }
-    }
-
-    if (legacy_syntax)
+    if (needs_legacy_glsl_syntax(gl_info))
     {
         if (shadow)
             base = "shadow";
     {
         if (shadow)
             base = "shadow";
@@ -3331,7 +3327,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     sample_function->offset_size = offset ? deriv_size : 0;
     sample_function->coord_mask = (1u << coord_size) - 1;
     sample_function->deriv_mask = (1u << deriv_size) - 1;
     sample_function->offset_size = offset ? deriv_size : 0;
     sample_function->coord_mask = (1u << coord_size) - 1;
     sample_function->deriv_mask = (1u << deriv_size) - 1;
-    sample_function->output_single_component = shadow && !legacy_syntax;
+    sample_function->output_single_component = shadow && !needs_legacy_glsl_syntax(gl_info);
 }
 
 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx,
 }
 
 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx,
@@ -3452,7 +3448,6 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
         const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset,
         const char *coord_reg_fmt, ...)
 {
         const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset,
         const char *coord_reg_fmt, ...)
 {
-    static const struct wined3d_shader_texel_offset dummy_offset = {0, 0, 0};
     const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
     char dst_swizzle[6];
     struct color_fixup_desc fixup;
     const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
     char dst_swizzle[6];
     struct color_fixup_desc fixup;
@@ -3521,26 +3516,6 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
                 break;
         }
     }
                 break;
         }
     }
-    if (sample_function->emulate_lod)
-    {
-        if (strcmp(bias, "0")) FIXME("Don't know how to emulate lod level %s\n", bias);
-        switch (sample_function->emulate_lod)
-        {
-            case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
-                if (!dx) dx = "vec2(0.0, 0.0)";
-                if (!dy) dy = "vec2(0.0, 0.0)";
-                break;
-
-            case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
-                if (!dx) dx = "vec3(0.0, 0.0, 0.0)";
-                if (!dy) dy = "vec3(0.0, 0.0, 0.0)";
-                break;
-
-            default:
-                break;
-        }
-        if (!offset) offset = &dummy_offset;
-    }
     if (dx && dy)
         shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy);
     else if (bias)
     if (dx && dy)
         shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy);
     else if (bias)
@@ -3562,7 +3537,7 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_
         shader_glsl_color_correction(ins, fixup);
 }
 
         shader_glsl_color_correction(ins, fixup);
 }
 
-static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer)
+static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOOL use_viewport_index)
 {
     /* Write the final position.
      *
 {
     /* Write the final position.
      *
@@ -3571,8 +3546,16 @@ static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer)
      * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering
      * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow
      * a MAD. */
      * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering
      * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow
      * a MAD. */
-    shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
-    shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
+    if (use_viewport_index)
+    {
+        shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup[gl_ViewportIndex].y;\n");
+        shader_addline(buffer, "gl_Position.xy += pos_fixup[gl_ViewportIndex].zw * gl_Position.ww;\n");
+    }
+    else
+    {
+        shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
+        shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
+    }
 
     /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix()
      * in utils.c
 
     /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix()
      * in utils.c
@@ -4898,10 +4881,11 @@ static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
 static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
 {
     unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset;
 static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
 {
     unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset;
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
 
     shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
     if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL])
 
     shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
     if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL])
-        shader_glsl_fixup_position(ins->ctx->buffer);
+        shader_glsl_fixup_position(ins->ctx->buffer, reg_maps->viewport_array);
 
     if (!stream)
         shader_addline(ins->ctx->buffer, "EmitVertex();\n");
 
     if (!stream)
         shader_addline(ins->ctx->buffer, "EmitVertex();\n");
@@ -5756,6 +5740,71 @@ static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins)
     shader_addline(buffer, ")%s);\n", dst_swizzle);
 }
 
     shader_addline(buffer, ")%s);\n", dst_swizzle);
 }
 
+static void shader_glsl_sample_info(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
+    struct wined3d_string_buffer *buffer = ins->ctx->buffer;
+    const struct wined3d_shader_dst_param *dst = ins->dst;
+    const struct wined3d_shader_src_param *src = ins->src;
+    enum wined3d_shader_resource_type resource_type;
+    enum wined3d_data_type dst_data_type;
+    unsigned int resource_idx, bind_idx;
+    char dst_swizzle[6];
+    DWORD write_mask;
+
+    dst_data_type = dst->reg.data_type;
+    if (ins->flags == WINED3DSI_SAMPLE_INFO_UINT)
+        dst_data_type = WINED3D_DATA_UINT;
+    else if (ins->flags)
+        FIXME("Unhandled flags %#x.\n", ins->flags);
+
+    write_mask = shader_glsl_append_dst_ext(buffer, ins, dst, dst_data_type);
+    shader_glsl_get_swizzle(src, FALSE, write_mask, dst_swizzle);
+
+    if (dst_data_type == WINED3D_DATA_UINT)
+        shader_addline(buffer, "uvec4(");
+    else
+        shader_addline(buffer, "vec4(");
+
+    if (src->reg.type == WINED3DSPR_RASTERIZER)
+    {
+        if (gl_info->supported[ARB_SAMPLE_SHADING])
+        {
+            shader_addline(buffer, "gl_NumSamples");
+        }
+        else
+        {
+            FIXME("OpenGL implementation does not support ARB_sample_shading.\n");
+            shader_addline(buffer, "1");
+        }
+    }
+    else
+    {
+        resource_idx = src->reg.idx[0].offset;
+        resource_type = reg_maps->resource_info[resource_idx].type;
+        if (resource_type >= ARRAY_SIZE(resource_type_info))
+        {
+            ERR("Unexpected resource type %#x.\n", resource_type);
+            return;
+        }
+        bind_idx = shader_glsl_find_sampler(&reg_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT);
+
+        if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES])
+        {
+            shader_addline(buffer, "textureSamples(%s_sampler%u)",
+                    shader_glsl_get_prefix(reg_maps->shader_version.type), bind_idx);
+        }
+        else
+        {
+            FIXME("textureSamples() is not supported.\n");
+            shader_addline(buffer, "1");
+        }
+    }
+
+    shader_addline(buffer, ", 0, 0, 0)%s);\n", dst_swizzle);
+}
+
 static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
 static void shader_glsl_ld(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
@@ -6498,7 +6547,7 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
         semantic_idx = input->semantic_idx;
         shader_glsl_write_mask_to_str(input->mask, reg_mask);
 
         semantic_idx = input->semantic_idx;
         shader_glsl_write_mask_to_str(input->mask, reg_mask);
 
-        if (args->vp_mode == vertexshader)
+        if (args->vp_mode == WINED3D_VP_MODE_SHADER)
         {
             if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx)
             {
         {
             if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx)
             {
@@ -6514,6 +6563,14 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
                 shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n",
                         input->register_idx, reg_mask);
             }
                 shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n",
                         input->register_idx, reg_mask);
             }
+            else if (input->sysval_semantic == WINED3D_SV_SAMPLE_INDEX)
+            {
+                if (gl_info->supported[ARB_SAMPLE_SHADING])
+                    shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_SampleID);\n",
+                            input->register_idx, reg_mask);
+                else
+                    FIXME("ARB_sample_shading is not supported.\n");
+            }
             else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx)
             {
                 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
             else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx)
             {
                 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
@@ -6522,6 +6579,14 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
                 else
                     FIXME("ARB_fragment_layer_viewport is not supported.\n");
             }
                 else
                     FIXME("ARB_fragment_layer_viewport is not supported.\n");
             }
+            else if (input->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx)
+            {
+                if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+                    shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_ViewportIndex);\n",
+                            input->register_idx, reg_mask);
+                else
+                    FIXME("ARB_viewport_array is not supported.\n");
+            }
             else
             {
                 if (input->sysval_semantic)
             else
             {
                 if (input->sysval_semantic)
@@ -6537,7 +6602,7 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w
             if (args->pointsprite)
                 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n",
                         shader->u.ps.input_reg_map[input->register_idx]);
             if (args->pointsprite)
                 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n",
                         shader->u.ps.input_reg_map[input->register_idx]);
-            else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx))
+            else if (args->vp_mode == WINED3D_VP_MODE_NONE && args->texcoords_initialized & (1u << semantic_idx))
                 shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n",
                         shader->u.ps.input_reg_map[input->register_idx], reg_mask,
                         needs_legacy_glsl_syntax(gl_info)
                 shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n",
                         shader->u.ps.input_reg_map[input->register_idx], reg_mask,
                         needs_legacy_glsl_syntax(gl_info)
@@ -6813,6 +6878,11 @@ static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv
             shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n",
                     output->register_idx, reg_mask);
         }
             shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n",
                     output->register_idx, reg_mask);
         }
+        else if (output->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx)
+        {
+            shader_addline(buffer, "gl_ViewportIndex = floatBitsToInt(outputs[%u])%s;\n",
+                    output->register_idx, reg_mask);
+        }
         else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
         {
             shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask);
         else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
         {
             shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask);
@@ -7237,6 +7307,8 @@ static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer,
         shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n");
     if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT])
         shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n");
         shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n");
     if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT])
         shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n");
+    if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES])
+        shader_addline(buffer, "#extension GL_ARB_shader_texture_image_samples : enable\n");
     if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK])
         shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n");
     if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING])
     if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK])
         shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n");
     if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING])
@@ -7249,6 +7321,8 @@ static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer,
         shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n");
     if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
         shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
         shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n");
     if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
         shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
+    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+        shader_addline(buffer, "#extension GL_ARB_viewport_array : enable\n");
     if (gl_info->supported[EXT_GPU_SHADER4])
         shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
     if (gl_info->supported[EXT_TEXTURE_ARRAY])
     if (gl_info->supported[EXT_GPU_SHADER4])
         shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
     if (gl_info->supported[EXT_TEXTURE_ARRAY])
@@ -7274,6 +7348,9 @@ static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_in
         shader_glsl_generate_fog_code(buffer, gl_info, args->fog);
 
     shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1);
         shader_glsl_generate_fog_code(buffer, gl_info, args->fog);
 
     shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1);
+
+    if (reg_maps->sample_mask)
+        shader_addline(buffer, "gl_SampleMask[0] = floatBitsToInt(sample_mask);\n");
 }
 
 /* Context activation is done by the caller. */
 }
 
 /* Context activation is done by the caller. */
@@ -7310,6 +7387,8 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
         shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n");
     if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
         shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n");
         shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n");
     if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT])
         shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n");
+    if (gl_info->supported[ARB_SAMPLE_SHADING])
+        shader_addline(buffer, "#extension GL_ARB_sample_shading : enable\n");
     if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
         shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
     /* The spec says that it doesn't have to be explicitly enabled, but the
     if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
         shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
     /* The spec says that it doesn't have to be explicitly enabled, but the
@@ -7362,7 +7441,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
         shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts);
     }
 
         shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts);
     }
 
-    if (version->major < 3 || args->vp_mode != vertexshader)
+    if (version->major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER)
     {
         shader_addline(buffer, "uniform struct\n{\n");
         shader_addline(buffer, "    vec4 color;\n");
     {
         shader_addline(buffer, "uniform struct\n{\n");
         shader_addline(buffer, "    vec4 color;\n");
@@ -7396,7 +7475,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
     {
         unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input);
 
     {
         unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input);
 
-        if (args->vp_mode == vertexshader && reg_maps->input_registers)
+        if (args->vp_mode == WINED3D_VP_MODE_SHADER && reg_maps->input_registers)
             shader_glsl_declare_shader_inputs(gl_info, buffer, in_count,
                     shader->u.ps.interpolation_mode, version->major >= 4);
         shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count);
             shader_glsl_declare_shader_inputs(gl_info, buffer, in_count,
                     shader->u.ps.interpolation_mode, version->major >= 4);
         shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count);
@@ -7482,6 +7561,9 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
 
     shader_addline(buffer, "void main()\n{\n");
 
 
     shader_addline(buffer, "void main()\n{\n");
 
+    if (reg_maps->sample_mask)
+        shader_addline(buffer, "float sample_mask = uintBitsToFloat(0xffffffffu);\n");
+
     /* Direct3D applications expect integer vPos values, while OpenGL drivers
      * add approximately 0.5. This causes off-by-one problems as spotted by
      * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly
     /* Direct3D applications expect integer vPos values, while OpenGL drivers
      * add approximately 0.5. This causes off-by-one problems as spotted by
      * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly
@@ -7510,7 +7592,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
                     "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n");
     }
 
                     "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n");
     }
 
-    if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader)
+    if (reg_maps->shader_version.major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER)
     {
         unsigned int i;
         WORD map = reg_maps->texcoord;
     {
         unsigned int i;
         WORD map = reg_maps->texcoord;
@@ -7604,7 +7686,7 @@ static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_in
         shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
 
     if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
         shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
 
     if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
-        shader_glsl_fixup_position(buffer);
+        shader_glsl_fixup_position(buffer, FALSE);
 }
 
 /* Context activation is done by the caller. */
 }
 
 /* Context activation is done by the caller. */
@@ -7842,7 +7924,7 @@ static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_in
     shader_addline(buffer, "setup_ds_output(ds_out);\n");
 
     if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
     shader_addline(buffer, "setup_ds_output(ds_out);\n");
 
     if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
-        shader_glsl_fixup_position(buffer);
+        shader_glsl_fixup_position(buffer, FALSE);
 }
 
 static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context,
 }
 
 static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context,
@@ -7946,7 +8028,11 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     struct wined3d_string_buffer *buffer = &priv->shader_buffer;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     struct wined3d_string_buffer *buffer = &priv->shader_buffer;
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_shader_signature_element *output;
+    enum wined3d_primitive_type primitive_type;
     struct shader_glsl_ctx_priv priv_ctx;
     struct shader_glsl_ctx_priv priv_ctx;
+    unsigned int max_vertices;
+    unsigned int i, j;
     GLuint shader_id;
 
     memset(&priv_ctx, 0, sizeof(priv_ctx));
     GLuint shader_id;
 
     memset(&priv_ctx, 0, sizeof(priv_ctx));
@@ -7958,16 +8044,42 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
 
     shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
 
 
     shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
 
-    shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(shader->u.gs.input_type));
+    primitive_type = shader->u.gs.input_type ? shader->u.gs.input_type : args->primitive_type;
+    shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(primitive_type));
     if (shader->u.gs.instance_count > 1)
         shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count);
     shader_addline(buffer, ") in;\n");
     if (shader->u.gs.instance_count > 1)
         shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count);
     shader_addline(buffer, ") in;\n");
+
+    primitive_type = shader->u.gs.output_type ? shader->u.gs.output_type : args->primitive_type;
+    if (!(max_vertices = shader->u.gs.vertices_out))
+    {
+        switch (args->primitive_type)
+        {
+            case WINED3D_PT_POINTLIST:
+                max_vertices = 1;
+                break;
+            case WINED3D_PT_LINELIST:
+                max_vertices = 2;
+                break;
+            case WINED3D_PT_TRIANGLELIST:
+                max_vertices = 3;
+                break;
+            default:
+                FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(args->primitive_type));
+                break;
+        }
+    }
     shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n",
     shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n",
-            glsl_primitive_type_from_d3d(shader->u.gs.output_type), shader->u.gs.vertices_out);
+            glsl_primitive_type_from_d3d(primitive_type), max_vertices);
     shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
 
     if (!gl_info->supported[ARB_CLIP_CONTROL])
     shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input);
 
     if (!gl_info->supported[ARB_CLIP_CONTROL])
-        shader_addline(buffer, "uniform vec4 pos_fixup;\n");
+    {
+        shader_addline(buffer, "uniform vec4 pos_fixup");
+        if (reg_maps->viewport_array)
+            shader_addline(buffer, "[%u]", WINED3D_MAX_VIEWPORTS);
+        shader_addline(buffer, ";\n");
+    }
 
     if (is_rasterization_disabled(shader))
     {
 
     if (is_rasterization_disabled(shader))
     {
@@ -7978,9 +8090,29 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
         shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count,
                 gl_info, TRUE, args->interpolation_mode);
     }
         shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count,
                 gl_info, TRUE, args->interpolation_mode);
     }
+
     shader_addline(buffer, "void main()\n{\n");
     shader_addline(buffer, "void main()\n{\n");
-    if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
-        return 0;
+    if (shader->function)
+    {
+        if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
+            return 0;
+    }
+    else
+    {
+        for (i = 0; i < max_vertices; ++i)
+        {
+            for (j = 0; j < shader->output_signature.element_count; ++j)
+            {
+                output = &shader->output_signature.elements[j];
+                shader_addline(buffer, "gs_out[%u] = shader_in[%u].reg[%u];\n",
+                        output->register_idx, i, output->register_idx);
+            }
+            shader_addline(buffer, "setup_gs_output(gs_out);\n");
+            if (!gl_info->supported[ARB_CLIP_CONTROL])
+                shader_glsl_fixup_position(buffer, FALSE);
+            shader_addline(buffer, "EmitVertex();\n");
+        }
+    }
     shader_addline(buffer, "}\n");
 
     shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER));
     shader_addline(buffer, "}\n");
 
     shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER));
@@ -8910,7 +9042,7 @@ static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buf
 }
 
 static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color,
 }
 
 static void shader_glsl_ffp_fragment_op(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;
 
 {
     const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
 
@@ -8921,10 +9053,7 @@ static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, un
     else
         dstmask = ".w";
 
     else
         dstmask = ".w";
 
-    if (dst == tempreg)
-        dstreg = "temp_reg";
-    else
-        dstreg = "ret";
+    dstreg = tmp_dst ? "temp_reg" : "ret";
 
     arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0);
     arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1);
 
     arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0);
     arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1);
@@ -9094,7 +9223,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
             tfactor_used = TRUE;
         if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
             tempreg_used = TRUE;
             tfactor_used = TRUE;
         if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
             tempreg_used = TRUE;
-        if (settings->op[stage].dst == tempreg)
+        if (settings->op[stage].tmp_dst)
             tempreg_used = TRUE;
         if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
             tss_const_map |= 1u << stage;
             tempreg_used = TRUE;
         if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
             tss_const_map |= 1u << stage;
@@ -9290,12 +9419,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
         if (!(tex_map & (1u << stage)))
             continue;
 
         if (!(tex_map & (1u << stage)))
             continue;
 
-        if (settings->op[stage].projected == proj_none)
+        if (settings->op[stage].projected == WINED3D_PROJECTION_NONE)
         {
             proj = FALSE;
         }
         {
             proj = FALSE;
         }
-        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)
         {
             proj = TRUE;
         }
         {
             proj = TRUE;
         }
@@ -9378,12 +9507,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
             shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1);
 
             /* With projective textures, texbem only divides the static
             shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1);
 
             /* With projective textures, texbem only divides the static
-             * texture coord, not the displacement, so multiply the
+             * texture coordinate, not the displacement, so multiply the
              * displacement with the dividing parameter before passing it to
              * TXP. */
              * displacement with the dividing parameter before passing it to
              * TXP. */
-            if (settings->op[stage].projected != proj_none)
+            if (settings->op[stage].projected != WINED3D_PROJECTION_NONE)
             {
             {
-                if (settings->op[stage].projected == proj_count4)
+                if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4)
                 {
                     shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n",
                             stage, stage);
                 {
                     shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n",
                             stage, stage);
@@ -9408,7 +9537,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
                 shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n",
                         stage, stage - 1, stage - 1, stage - 1);
         }
                 shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n",
                         stage, stage - 1, stage - 1, stage - 1);
         }
-        else if (settings->op[stage].projected == proj_count3)
+        else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT3)
         {
             shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n",
                     stage, texture_function, stage, stage);
         {
             shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n",
                     stage, texture_function, stage, stage);
@@ -9460,23 +9589,23 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
 
         if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
         {
 
         if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
         {
-            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+            shader_glsl_ffp_fragment_op(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)
         {
                     settings->op[stage].cop, settings->op[stage].carg0,
                     settings->op[stage].carg1, settings->op[stage].carg2);
         }
         else if (op_equal)
         {
-            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].dst,
+            shader_glsl_ffp_fragment_op(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)
         {
                     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)
         {
-            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+            shader_glsl_ffp_fragment_op(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);
                     settings->op[stage].cop, settings->op[stage].carg0,
                     settings->op[stage].carg1, settings->op[stage].carg2);
-            shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].dst,
+            shader_glsl_ffp_fragment_op(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);
         }
                     settings->op[stage].aop, settings->op[stage].aarg0,
                     settings->op[stage].aarg1, settings->op[stage].aarg2);
         }
@@ -10776,6 +10905,7 @@ static unsigned int shader_glsl_get_shader_model(const struct wined3d_gl_info *g
             && gl_info->supported[ARB_SHADER_IMAGE_SIZE]
             && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]
             && gl_info->supported[ARB_TESSELLATION_SHADER]
             && gl_info->supported[ARB_SHADER_IMAGE_SIZE]
             && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]
             && gl_info->supported[ARB_TESSELLATION_SHADER]
+            && gl_info->supported[ARB_TEXTURE_COMPRESSION_BPTC]
             && gl_info->supported[ARB_TEXTURE_GATHER]
             && gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
         return 5;
             && gl_info->supported[ARB_TEXTURE_GATHER]
             && gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
         return 5;
@@ -11033,7 +11163,7 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB
     /* WINED3DSIH_SAMPLE_C                         */ shader_glsl_sample_c,
     /* WINED3DSIH_SAMPLE_C_LZ                      */ shader_glsl_sample_c,
     /* WINED3DSIH_SAMPLE_GRAD                      */ shader_glsl_sample,
     /* WINED3DSIH_SAMPLE_C                         */ shader_glsl_sample_c,
     /* WINED3DSIH_SAMPLE_C_LZ                      */ shader_glsl_sample_c,
     /* WINED3DSIH_SAMPLE_GRAD                      */ shader_glsl_sample,
-    /* WINED3DSIH_SAMPLE_INFO                      */ NULL,
+    /* WINED3DSIH_SAMPLE_INFO                      */ shader_glsl_sample_info,
     /* WINED3DSIH_SAMPLE_LOD                       */ shader_glsl_sample,
     /* WINED3DSIH_SAMPLE_POS                       */ NULL,
     /* WINED3DSIH_SETP                             */ NULL,
     /* WINED3DSIH_SAMPLE_LOD                       */ shader_glsl_sample,
     /* WINED3DSIH_SAMPLE_POS                       */ NULL,
     /* WINED3DSIH_SETP                             */ NULL,
@@ -11978,3 +12108,854 @@ const struct fragment_pipeline glsl_fragment_pipe =
     shader_glsl_color_fixup_supported,
     glsl_fragment_pipe_state_template,
 };
     shader_glsl_color_fixup_supported,
     glsl_fragment_pipe_state_template,
 };
+
+struct glsl_blitter_args
+{
+    GLenum texture_type;
+    struct color_fixup_desc fixup;
+    unsigned short padding;
+};
+
+struct glsl_blitter_program
+{
+    struct wine_rb_entry entry;
+    struct glsl_blitter_args args;
+    GLuint id;
+};
+
+struct wined3d_glsl_blitter
+{
+    struct wined3d_blitter blitter;
+    struct wined3d_string_buffer_list string_buffers;
+    struct wine_rb_tree programs;
+    GLuint palette_texture;
+};
+
+static int glsl_blitter_args_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct glsl_blitter_args *a = key;
+    const struct glsl_blitter_args *b = &WINE_RB_ENTRY_VALUE(entry, const struct glsl_blitter_program, entry)->args;
+
+    return memcmp(a, b, sizeof(*a));
+}
+
+/* Context activation is done by the caller. */
+static void glsl_free_blitter_program(struct wine_rb_entry *entry, void *ctx)
+{
+    struct glsl_blitter_program *program = WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry);
+    struct wined3d_context *context = ctx;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glDeleteProgram(program->id));
+    checkGLcall("glDeleteProgram()");
+    heap_free(program);
+}
+
+/* Context activation is done by the caller. */
+static void glsl_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_glsl_blitter *glsl_blitter;
+    struct wined3d_blitter *next;
+
+    if ((next = blitter->next))
+        next->ops->blitter_destroy(next, context);
+
+    glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
+
+    if (glsl_blitter->palette_texture)
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &glsl_blitter->palette_texture);
+
+    wine_rb_destroy(&glsl_blitter->programs, glsl_free_blitter_program, context);
+    string_buffer_list_cleanup(&glsl_blitter->string_buffers);
+
+    heap_free(glsl_blitter);
+}
+
+static void glsl_blitter_generate_p8_shader(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
+        const char *output, const char *tex_type, const char *swizzle)
+{
+    shader_addline(buffer, "uniform sampler1D sampler_palette;\n");
+    shader_addline(buffer, "\nvoid main()\n{\n");
+    /* The alpha-component contains the palette index. */
+    shader_addline(buffer, "    float index = texture%s(sampler, out_texcoord.%s).%c;\n",
+            needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle,
+            gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x');
+    /* Scale the index by 255/256 and add a bias of 0.5 in order to sample in
+     * the middle. */
+    shader_addline(buffer, "    index = (index * 255.0 + 0.5) / 256.0;\n");
+    shader_addline(buffer, "    %s = texture%s(sampler_palette, index);\n",
+            output, needs_legacy_glsl_syntax(gl_info) ? "1D" : "");
+    shader_addline(buffer, "}\n");
+}
+
+static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
+        const char *tex_type)
+{
+    enum complex_fixup complex_fixup = get_complex_fixup(args->fixup);
+    char chroma, luminance;
+    const char *tex;
+
+    /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit
+     * macropixel, giving effectively 16 bits per pixel. The color consists of
+     * a luminance(Y) and two chroma(U and V) values. Each macropixel has two
+     * luminance values, one for each single pixel it contains, and one U and
+     * one V value shared between both pixels.
+     *
+     * The data is loaded into an A8L8 texture. With YUY2, the luminance
+     * component contains the luminance and alpha the chroma. With UYVY it is
+     * vice versa. Thus take the format into account when generating the read
+     * swizzles
+     *
+     * Reading the Y value is straightforward - just sample the texture. The
+     * hardware takes care of filtering in the horizontal and vertical
+     * direction.
+     *
+     * Reading the U and V values is harder. We have to avoid filtering
+     * horizontally, because that would mix the U and V values of one pixel or
+     * two adjacent pixels.  Thus floor the texture coordinate and add 0.5 to
+     * get an unfiltered read, regardless of the filtering setting. Vertical
+     * filtering works automatically though - the U and V values of two rows
+     * are mixed nicely.
+     *
+     * Apart of avoiding filtering issues, the code has to know which value it
+     * just read, and where it can find the other one. To determine this, it
+     * checks if it sampled an even or odd pixel, and shifts the 2nd read
+     * accordingly.
+     *
+     * Handling horizontal filtering of U and V values requires reading a 2nd
+     * pair of pixels, extracting U and V and mixing them. This is not
+     * implemented yet.
+     *
+     * An alternative implementation idea is to load the texture as A8R8G8B8
+     * texture, with width / 2. This way one read gives all 3 values, finding
+     * U and V is easy in an unfiltered situation. Finding the luminance on
+     * the other hand requires finding out if it is an odd or even pixel. The
+     * real drawback of this approach is filtering. This would have to be
+     * emulated completely in the shader, reading up two 2 packed pixels in up
+     * to 2 rows and interpolating both horizontally and vertically. Beyond
+     * that it would require adjustments to the texture handling code to deal
+     * with the width scaling. */
+
+    if (complex_fixup == COMPLEX_FIXUP_UYVY)
+    {
+        chroma = 'x';
+        luminance = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y';
+    }
+    else
+    {
+        chroma = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y';
+        luminance = 'x';
+    }
+
+    tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : "";
+
+    /* First we have to read the chroma values. This means we need at least
+     * two pixels (no filtering), or 4 pixels (with filtering). To get the
+     * unmodified chroma, we have to rid ourselves of the filtering when we
+     * sample the texture. */
+    shader_addline(buffer, "    texcoord.xy = out_texcoord.xy;\n");
+    /* We must not allow filtering between pixel x and x+1, this would mix U
+     * and V. Vertical filtering is ok. However, bear in mind that the pixel
+     * center is at 0.5, so add 0.5. */
+    shader_addline(buffer, "    texcoord.x = (floor(texcoord.x * size.x) + 0.5) / size.x;\n");
+    shader_addline(buffer, "    luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma);
+
+    /* 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. */
+    /* Put the value into either of the chroma values. */
+    shader_addline(buffer, "    bool even = fract(texcoord.x * size.x * 0.5) < 0.5;\n");
+    shader_addline(buffer, "    if (even)\n");
+    shader_addline(buffer, "        chroma.y = luminance;\n");
+    shader_addline(buffer, "    else\n");
+    shader_addline(buffer, "        chroma.x = luminance;\n");
+
+    /* Sample pixel 2. If we read an even pixel, sample the pixel right to the
+     * current one. Otherwise, sample the left pixel. */
+    shader_addline(buffer, "    texcoord.x += even ? 1.0 / size.x : -1.0 / size.x;\n");
+    shader_addline(buffer, "    luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma);
+
+    /* Put the value into the other chroma. */
+    shader_addline(buffer, "    if (even)\n");
+    shader_addline(buffer, "        chroma.x = luminance;\n");
+    shader_addline(buffer, "    else\n");
+    shader_addline(buffer, "        chroma.y = luminance;\n");
+
+    /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
+     * the current one and lerp the two U and V values. */
+
+    /* This gives the correctly filtered luminance value. */
+    shader_addline(buffer, "    luminance = texture%s(sampler, out_texcoord.xy).%c;\n", tex, luminance);
+}
+
+static void gen_yv12_read(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const char *tex_type)
+{
+    char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x';
+    const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : "";
+
+    /* YV12 surfaces contain a WxH sized luminance plane, followed by a
+     * (W/2)x(H/2) V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So
+     * the effective bitdepth is 12 bits per pixel. Since the U and V planes
+     * have only half the pitch of the luminance plane, the packing into the
+     * gl texture is a bit unfortunate. If the whole texture is interpreted as
+     * luminance data it looks approximately like this:
+     *
+     *        +----------------------------------+----
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |   2
+     *        |            LUMINANCE             |   -
+     *        |                                  |   3
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        +----------------+-----------------+----
+     *        |                |                 |
+     *        |  V even rows   |  V odd rows     |
+     *        |                |                 |   1
+     *        +----------------+------------------   -
+     *        |                |                 |   3
+     *        |  U even rows   |  U odd rows     |
+     *        |                |                 |
+     *        +----------------+-----------------+----
+     *        |                |                 |
+     *        |     0.5        |       0.5       |
+     *
+     * So it appears as if there are 4 chroma images, but in fact the odd rows
+     * in the chroma images are in the same row as the even ones. So it is
+     * kinda tricky to read. */
+
+    /* First sample the chroma values. */
+    shader_addline(buffer, "    texcoord.xy = out_texcoord.xy;\n");
+    /* The chroma planes have only half the width. */
+    shader_addline(buffer, "    texcoord.x *= 0.5;\n");
+
+    /* The first value is between 2/3 and 5/6 of the texture's height, so
+     * scale+bias the coordinate. Also read the right side of the image when
+     * reading odd lines.
+     *
+     * Don't forget to clamp the y values in into the range, otherwise we'll
+     * get filtering bleeding. */
+
+    /* Read odd lines from the right side (add 0.5 to the x coordinate). */
+    shader_addline(buffer, "    if (fract(floor(texcoord.y * size.y) * 0.5 + 1.0 / 6.0) >= 0.5)\n");
+    shader_addline(buffer, "        texcoord.x += 0.5;\n");
+
+    /* Clamp, keep the half pixel origin in mind. */
+    shader_addline(buffer, "    texcoord.y = clamp(2.0 / 3.0 + texcoord.y / 6.0, "
+            "2.0 / 3.0 + 0.5 / size.y, 5.0 / 6.0 - 0.5 / size.y);\n");
+
+    shader_addline(buffer, "    chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+
+    /* The other chroma value is 1/6th of the texture lower, from 5/6th to
+     * 6/6th No need to clamp because we're just reusing the already clamped
+     * value from above. */
+    shader_addline(buffer, "    texcoord.y += 1.0 / 6.0;\n");
+    shader_addline(buffer, "    chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+
+    /* Sample the luminance value. It is in the top 2/3rd of the texture, so
+     * scale the y coordinate.  Clamp the y coordinate to prevent the chroma
+     * values from bleeding into the sampled luminance values due to
+     * filtering. */
+    shader_addline(buffer, "    texcoord.xy = out_texcoord.xy;\n");
+    /* Multiply the y coordinate by 2/3 and clamp it. */
+    shader_addline(buffer, "    texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n");
+    shader_addline(buffer, "    luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+}
+
+static void gen_nv12_read(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const char *tex_type)
+{
+    char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x';
+    const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : "";
+
+    /* NV12 surfaces contain a WxH sized luminance plane, followed by a
+     * (W/2)x(H/2) sized plane where each component is an UV pair. So the
+     * effective bitdepth is 12 bits per pixel. If the whole texture is
+     * interpreted as luminance data it looks approximately like this:
+     *
+     *        +----------------------------------+----
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |   2
+     *        |            LUMINANCE             |   -
+     *        |                                  |   3
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        +----------------------------------+----
+     *        |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV|
+     *        |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV|
+     *        |                                  |   1
+     *        |                                  |   -
+     *        |                                  |   3
+     *        |                                  |
+     *        |                                  |
+     *        +----------------------------------+---- */
+
+    /* First sample the chroma values. */
+    shader_addline(buffer, "    texcoord.xy = out_texcoord.xy;\n");
+    /* We only have half the number of chroma pixels. */
+    shader_addline(buffer, "    texcoord.x *= 0.5;\n");
+    shader_addline(buffer, "    texcoord.y = (texcoord.y + 2.0) / 3.0;\n");
+
+    /* We must not allow filtering horizontally, this would mix U and V.
+     * Vertical filtering is ok. However, bear in mind that the pixel center
+     * is at 0.5, so add 0.5. */
+
+    /* Convert to non-normalised coordinates so we can find the individual
+     * pixel. */
+    shader_addline(buffer, "    texcoord.x = floor(texcoord.x * size.x);\n");
+    /* Multiply by 2 since chroma components are stored in UV pixel pairs, add
+     * 0.5 to hit the center of the pixel. Then convert back to normalised
+     * coordinates. */
+    shader_addline(buffer, "    texcoord.x = (texcoord.x * 2.0 + 0.5) / size.x;\n");
+    /* Clamp, keep the half pixel origin in mind. */
+    shader_addline(buffer, "    texcoord.y = max(texcoord.y, 2.0 / 3.0 + 0.5 / size.y);\n");
+
+    shader_addline(buffer, "    chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+    /* Add 1.0 / size.x to sample the adjacent texel. */
+    shader_addline(buffer, "    texcoord.x += 1.0 / size.x;\n");
+    shader_addline(buffer, "    chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+
+    /* Sample the luminance value. It is in the top 2/3rd of the texture, so
+     * scale the y coordinate. Clamp the y coordinate to prevent the chroma
+     * values from bleeding into the sampled luminance values due to
+     * filtering. */
+    shader_addline(buffer, "    texcoord.xy = out_texcoord.xy;\n");
+    /* Multiply the y coordinate by 2/3 and clamp it. */
+    shader_addline(buffer, "    texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n");
+    shader_addline(buffer, "    luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component);
+}
+
+static void glsl_blitter_generate_yuv_shader(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
+        const char *output, const char *tex_type, const char *swizzle)
+{
+    enum complex_fixup complex_fixup = get_complex_fixup(args->fixup);
+
+    shader_addline(buffer, "const vec4 yuv_coef = vec4(1.403, -0.344, -0.714, 1.770);\n");
+    shader_addline(buffer, "float luminance;\n");
+    shader_addline(buffer, "vec2 texcoord;\n");
+    shader_addline(buffer, "vec2 chroma;\n");
+    shader_addline(buffer, "uniform vec2 size;\n");
+
+    shader_addline(buffer, "\nvoid main()\n{\n");
+
+    switch (complex_fixup)
+    {
+        case COMPLEX_FIXUP_UYVY:
+        case COMPLEX_FIXUP_YUY2:
+            gen_packed_yuv_read(buffer, gl_info, args, tex_type);
+            break;
+
+        case COMPLEX_FIXUP_YV12:
+            gen_yv12_read(buffer, gl_info, tex_type);
+            break;
+
+        case COMPLEX_FIXUP_NV12:
+            gen_nv12_read(buffer, gl_info, tex_type);
+            break;
+
+        default:
+            FIXME("Unsupported fixup %#x.\n", complex_fixup);
+            string_buffer_free(buffer);
+            return;
+    }
+
+    /* Calculate the final result. Formula is taken from
+     * http://www.fourcc.org/fccyvrgb.php. Note that the chroma
+     * ranges from -0.5 to 0.5. */
+    shader_addline(buffer, "\n    chroma.xy -= 0.5;\n");
+
+    shader_addline(buffer, "    %s.x = luminance + chroma.x * yuv_coef.x;\n", output);
+    shader_addline(buffer, "    %s.y = luminance + chroma.y * yuv_coef.y + chroma.x * yuv_coef.z;\n", output);
+    shader_addline(buffer, "    %s.z = luminance + chroma.y * yuv_coef.w;\n", output);
+
+    shader_addline(buffer, "}\n");
+}
+
+static void glsl_blitter_generate_plain_shader(struct wined3d_string_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
+        const char *output, const char *tex_type, const char *swizzle)
+{
+    shader_addline(buffer, "\nvoid main()\n{\n");
+    shader_addline(buffer, "    %s = texture%s(sampler, out_texcoord.%s);\n",
+            output, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
+    shader_glsl_color_correction_ext(buffer, output, WINED3DSP_WRITEMASK_ALL, args->fixup);
+    shader_addline(buffer, "}\n");
+}
+
+/* Context activation is done by the caller. */
+static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter,
+        const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args)
+{
+    static const struct
+    {
+        GLenum texture_target;
+        const char texture_type[7];
+        const char texcoord_swizzle[4];
+    }
+    texture_data[] =
+    {
+        {GL_TEXTURE_2D, "2D", "xy"},
+        {GL_TEXTURE_CUBE_MAP, "Cube", "xyz"},
+        {GL_TEXTURE_RECTANGLE_ARB, "2DRect", "xy"},
+    };
+    static const char vshader_main[] =
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(pos, 0.0, 1.0);\n"
+        "    out_texcoord = texcoord;\n"
+        "}\n";
+    enum complex_fixup complex_fixup = get_complex_fixup(args->fixup);
+    struct wined3d_string_buffer *buffer, *output;
+    GLuint program, vshader_id, fshader_id;
+    const char *tex_type, *swizzle, *ptr;
+    unsigned int i;
+    GLint loc;
+
+    for (i = 0; i < ARRAY_SIZE(texture_data); ++i)
+    {
+        if (args->texture_type == texture_data[i].texture_target)
+        {
+            tex_type = texture_data[i].texture_type;
+            swizzle = texture_data[i].texcoord_swizzle;
+            break;
+        }
+    }
+    if (i == ARRAY_SIZE(texture_data))
+    {
+        FIXME("Unsupported texture type %#x.\n", args->texture_type);
+        return 0;
+    }
+
+    program = GL_EXTCALL(glCreateProgram());
+
+    vshader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
+
+    buffer = string_buffer_get(&blitter->string_buffers);
+    shader_glsl_add_version_declaration(buffer, gl_info);
+    shader_addline(buffer, "%s vec2 pos;\n", get_attribute_keyword(gl_info));
+    shader_addline(buffer, "%s vec3 texcoord;\n", get_attribute_keyword(gl_info));
+    declare_out_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n");
+    shader_addline(buffer, vshader_main);
+
+    ptr = buffer->buffer;
+    GL_EXTCALL(glShaderSource(vshader_id, 1, &ptr, NULL));
+    GL_EXTCALL(glAttachShader(program, vshader_id));
+    GL_EXTCALL(glDeleteShader(vshader_id));
+
+    fshader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
+
+    string_buffer_clear(buffer);
+    shader_glsl_add_version_declaration(buffer, gl_info);
+    shader_addline(buffer, "uniform sampler%s sampler;\n", tex_type);
+    declare_in_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n");
+    if (!needs_legacy_glsl_syntax(gl_info))
+        shader_addline(buffer, "out vec4 ps_out[1];\n");
+
+    output = string_buffer_get(&blitter->string_buffers);
+    string_buffer_sprintf(output, "%s[0]", get_fragment_output(gl_info));
+
+    switch (complex_fixup)
+    {
+        case COMPLEX_FIXUP_P8:
+            glsl_blitter_generate_p8_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle);
+            break;
+        case COMPLEX_FIXUP_YUY2:
+        case COMPLEX_FIXUP_UYVY:
+        case COMPLEX_FIXUP_YV12:
+        case COMPLEX_FIXUP_NV12:
+            glsl_blitter_generate_yuv_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle);
+            break;
+        case COMPLEX_FIXUP_NONE:
+            glsl_blitter_generate_plain_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle);
+    }
+
+    string_buffer_release(&blitter->string_buffers, output);
+
+    ptr = buffer->buffer;
+    GL_EXTCALL(glShaderSource(fshader_id, 1, &ptr, NULL));
+    string_buffer_release(&blitter->string_buffers, buffer);
+    GL_EXTCALL(glAttachShader(program, fshader_id));
+    GL_EXTCALL(glDeleteShader(fshader_id));
+
+    GL_EXTCALL(glBindAttribLocation(program, 0, "pos"));
+    GL_EXTCALL(glBindAttribLocation(program, 1, "texcoord"));
+
+    if (!needs_legacy_glsl_syntax(gl_info))
+        GL_EXTCALL(glBindFragDataLocation(program, 0, "ps_out"));
+
+    GL_EXTCALL(glCompileShader(vshader_id));
+    print_glsl_info_log(gl_info, vshader_id, FALSE);
+    GL_EXTCALL(glCompileShader(fshader_id));
+    print_glsl_info_log(gl_info, fshader_id, FALSE);
+    GL_EXTCALL(glLinkProgram(program));
+    shader_glsl_validate_link(gl_info, program);
+
+    GL_EXTCALL(glUseProgram(program));
+    loc = GL_EXTCALL(glGetUniformLocation(program, "sampler"));
+    GL_EXTCALL(glUniform1i(loc, 0));
+    if (complex_fixup == COMPLEX_FIXUP_P8)
+    {
+        loc = GL_EXTCALL(glGetUniformLocation(program, "sampler_palette"));
+        GL_EXTCALL(glUniform1i(loc, 1));
+    }
+
+    return program;
+}
+
+/* Context activation is done by the caller. */
+static void glsl_blitter_upload_palette(struct wined3d_glsl_blitter *blitter,
+        struct wined3d_context *context, const struct wined3d_texture *texture)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_palette *palette;
+
+    palette = texture->swapchain ? texture->swapchain->palette : NULL;
+
+    if (!blitter->palette_texture)
+        gl_info->gl_ops.gl.p_glGenTextures(1, &blitter->palette_texture);
+
+    context_active_texture(context, gl_info, 1);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, blitter->palette_texture);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+    if (palette)
+    {
+        gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_BGRA,
+                GL_UNSIGNED_INT_8_8_8_8_REV, palette->colors);
+    }
+    else
+    {
+        static const DWORD black;
+
+        FIXME("P8 texture loaded without a palette.\n");
+        gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 1, 0, GL_BGRA,
+                GL_UNSIGNED_INT_8_8_8_8_REV, &black);
+    }
+
+    context_active_texture(context, gl_info, 0);
+}
+
+/* Context activation is done by the caller. */
+static struct glsl_blitter_program *glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
+        struct wined3d_context *context, const struct wined3d_texture *texture)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct glsl_blitter_program *program;
+    struct glsl_blitter_args args;
+    struct wine_rb_entry *entry;
+
+    memset(&args, 0, sizeof(args));
+    args.texture_type = texture->target;
+    args.fixup = texture->resource.format->color_fixup;
+
+    if ((entry = wine_rb_get(&blitter->programs, &args)))
+        return WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry);
+
+    if (!(program = heap_alloc(sizeof(*program))))
+    {
+        ERR("Failed to allocate blitter program memory.\n");
+        return NULL;
+    }
+
+    program->args = args;
+    if (!(program->id = glsl_blitter_generate_program(blitter, gl_info, &args)))
+    {
+        WARN("Failed to generate blitter program.\n");
+        heap_free(program);
+        return NULL;
+    }
+
+    if (wine_rb_put(&blitter->programs, &program->args, &program->entry) == -1)
+    {
+        ERR("Failed to store blitter program.\n");
+        GL_EXTCALL(glDeleteProgram(program->id));
+        heap_free(program);
+        return NULL;
+    }
+
+    return program;
+}
+
+static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context,
+        const struct wined3d_texture *src_texture, DWORD src_location,
+        const struct wined3d_texture *dst_texture, DWORD dst_location)
+{
+    const struct wined3d_resource *src_resource = &src_texture->resource;
+    const struct wined3d_resource *dst_resource = &dst_texture->resource;
+    const struct wined3d_format *src_format = src_resource->format;
+    const struct wined3d_format *dst_format = dst_resource->format;
+    BOOL decompress;
+
+    if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
+    {
+        if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+            blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
+        else
+            blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
+    }
+
+    if (blit_op != WINED3D_BLIT_OP_COLOR_BLIT)
+    {
+        TRACE("Unsupported blit_op %#x.\n", blit_op);
+        return FALSE;
+    }
+
+    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
+        return FALSE;
+
+    if (src_texture->target == GL_TEXTURE_2D_MULTISAMPLE
+            || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE
+            || src_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+            || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
+    {
+        TRACE("Multi-sample textures not supported.\n");
+        return FALSE;
+    }
+
+    /* We don't necessarily want to blit from resources without
+     * WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress
+     * compressed textures. */
+    decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
+            && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
+    if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
+    {
+        TRACE("Source or destination resource does not have GPU access.\n");
+        return FALSE;
+    }
+
+    if (!is_identity_fixup(dst_format->color_fixup)
+            && (dst_format->id != src_format->id || dst_location != WINED3D_LOCATION_DRAWABLE))
+    {
+        TRACE("Destination fixups are not supported.\n");
+        return FALSE;
+    }
+
+    TRACE("Returning supported.\n");
+    return TRUE;
+}
+
+static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
+        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 *colour_key, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_device *device = dst_texture->resource.device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_texture *staging_texture = NULL;
+    struct wined3d_glsl_blitter *glsl_blitter;
+    struct glsl_blitter_program *program;
+    struct wined3d_blitter *next;
+    unsigned int src_level;
+    GLint location;
+    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), colour_key, debug_d3dtexturefiltertype(filter));
+
+    if (!glsl_blitter_supported(op, context, src_texture, src_location, dst_texture, dst_location))
+    {
+        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, colour_key, filter);
+    }
+
+    glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
+
+    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))
+    {
+
+        /* 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. */
+        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);
+
+    if (dst_location == WINED3D_LOCATION_DRAWABLE)
+    {
+        d = *dst_rect;
+        wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d);
+        dst_rect = &d;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        GLenum buffer;
+
+        if (dst_location == WINED3D_LOCATION_DRAWABLE)
+        {
+            TRACE("Destination texture %p is onscreen.\n", dst_texture);
+            buffer = wined3d_texture_get_gl_buffer(dst_texture);
+        }
+        else
+        {
+            TRACE("Destination texture %p is offscreen.\n", dst_texture);
+            buffer = GL_COLOR_ATTACHMENT0;
+        }
+        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);
+    }
+
+    if (!(program = glsl_blitter_get_program(glsl_blitter, context, src_texture)))
+    {
+        ERR("Failed to get blitter program.\n");
+        return dst_location;
+    }
+    GL_EXTCALL(glUseProgram(program->id));
+    switch (get_complex_fixup(program->args.fixup))
+    {
+        case COMPLEX_FIXUP_P8:
+            glsl_blitter_upload_palette(glsl_blitter, context, src_texture);
+            break;
+
+        case COMPLEX_FIXUP_YUY2:
+        case COMPLEX_FIXUP_UYVY:
+        case COMPLEX_FIXUP_YV12:
+        case COMPLEX_FIXUP_NV12:
+            src_level = src_sub_resource_idx % src_texture->level_count;
+            location = GL_EXTCALL(glGetUniformLocation(program->id, "size"));
+            GL_EXTCALL(glUniform2f(location, wined3d_texture_get_level_pow2_width(src_texture, src_level),
+                    wined3d_texture_get_level_pow2_height(src_texture, src_level)));
+            break;
+
+        default:
+            break;
+    }
+    context_draw_shaded_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter);
+    GL_EXTCALL(glUseProgram(0));
+
+    if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))
+        gl_info->gl_ops.gl.p_glFlush();
+
+    if (staging_texture)
+        wined3d_texture_decref(staging_texture);
+
+    return dst_location;
+}
+
+static void glsl_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device,
+        unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
+        const RECT *draw_rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
+{
+    struct wined3d_blitter *next;
+
+    if ((next = blitter->next))
+        next->ops->blitter_clear(next, device, rt_count, fb, rect_count,
+                clear_rects, draw_rect, flags, color, depth, stencil);
+}
+
+static const struct wined3d_blitter_ops glsl_blitter_ops =
+{
+    glsl_blitter_destroy,
+    glsl_blitter_clear,
+    glsl_blitter_blit,
+};
+
+struct wined3d_blitter *wined3d_glsl_blitter_create(struct wined3d_blitter **next,
+        const struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_glsl_blitter *blitter;
+
+    if (device->shader_backend != &glsl_shader_backend)
+        return NULL;
+
+    if (!gl_info->supported[ARB_VERTEX_SHADER] || !gl_info->supported[ARB_FRAGMENT_SHADER])
+        return NULL;
+
+    if (!(blitter = heap_alloc(sizeof(*blitter))))
+    {
+        ERR("Failed to allocate blitter.\n");
+        return NULL;
+    }
+
+    TRACE("Created blitter %p.\n", blitter);
+
+    blitter->blitter.ops = &glsl_blitter_ops;
+    blitter->blitter.next = *next;
+    string_buffer_list_init(&blitter->string_buffers);
+    wine_rb_init(&blitter->programs, glsl_blitter_args_compare);
+    blitter->palette_texture = 0;
+    *next = &blitter->blitter;
+
+    return *next;
+}
index 0baa414..20db627 100644 (file)
@@ -69,6 +69,9 @@ static void nvts_activate_dimensions(const struct wined3d_state *state, DWORD st
                 gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
                 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
                 break;
                 gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
                 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
                 break;
+            default:
+                FIXME("Unhandled target %#x.\n", state->textures[stage]->target);
+                break;
         }
     }
     else
         }
     }
     else
index 8b7f17b..df73997 100644 (file)
@@ -95,6 +95,9 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
+    if (!size)
+        ERR("Attempting to create a zero-sized resource.\n");
+
     for (i = 0; i < ARRAY_SIZE(resource_types); ++i)
     {
         if (resource_types[i].type != type
     for (i = 0; i < ARRAY_SIZE(resource_types); ++i)
     {
         if (resource_types[i].type != type
@@ -191,19 +194,7 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
     resource->parent_ops = parent_ops;
     resource->resource_ops = resource_ops;
     resource->map_binding = WINED3D_LOCATION_SYSMEM;
     resource->parent_ops = parent_ops;
     resource->resource_ops = resource_ops;
     resource->map_binding = WINED3D_LOCATION_SYSMEM;
-
-    if (size)
-    {
-        if (!wined3d_resource_allocate_sysmem(resource))
-        {
-            ERR("Failed to allocate system memory.\n");
-            return E_OUTOFMEMORY;
-        }
-    }
-    else
-    {
-        resource->heap_memory = NULL;
-    }
+    resource->heap_memory = NULL;
 
     if (!(usage & WINED3DUSAGE_PRIVATE))
     {
 
     if (!(usage & WINED3DUSAGE_PRIVATE))
     {
@@ -212,8 +203,7 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
         {
             if (size > wined3d_device_get_available_texture_mem(device))
             {
         {
             if (size > wined3d_device_get_available_texture_mem(device))
             {
-                ERR("Out of adapter memory\n");
-                wined3d_resource_free_sysmem(resource);
+                ERR("Out of adapter memory.\n");
                 return WINED3DERR_OUTOFVIDEOMEMORY;
             }
             adapter_adjust_memory(device->adapter, size);
                 return WINED3DERR_OUTOFVIDEOMEMORY;
             }
             adapter_adjust_memory(device->adapter, size);
@@ -230,7 +220,7 @@ static void wined3d_resource_destroy_object(void *object)
     struct wined3d_resource *resource = object;
 
     wined3d_resource_free_sysmem(resource);
     struct wined3d_resource *resource = object;
 
     wined3d_resource_free_sysmem(resource);
-    context_resource_released(resource->device, resource, resource->type);
+    context_resource_released(resource->device, resource);
     wined3d_resource_release(resource);
 }
 
     wined3d_resource_release(resource);
 }
 
@@ -491,7 +481,10 @@ BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource)
     void *mem;
 
     if (!(mem = heap_alloc_zero(resource->size + align)))
     void *mem;
 
     if (!(mem = heap_alloc_zero(resource->size + align)))
+    {
+        ERR("Failed to allocate system memory.\n");
         return FALSE;
         return FALSE;
+    }
 
     p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1;
     *p = mem;
 
     p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1;
     *p = mem;
index 0513c9e..9075fc7 100644 (file)
@@ -419,6 +419,15 @@ static const struct wined3d_shader_frontend *shader_select_frontend(enum wined3d
     }
 }
 
     }
 }
 
+static enum wined3d_shader_type shader_get_shader_type(const struct wined3d_shader_desc *desc)
+{
+    if (desc->format == WINED3D_SHADER_BYTE_CODE_FORMAT_SM4)
+        return wined3d_get_sm4_shader_type(desc->byte_code, desc->byte_code_size);
+
+    FIXME("Could not get shader type for byte code format %#x.\n", desc->format);
+    return WINED3D_SHADER_TYPE_INVALID;
+}
+
 void string_buffer_clear(struct wined3d_string_buffer *buffer)
 {
     buffer->buffer[0] = '\0';
 void string_buffer_clear(struct wined3d_string_buffer *buffer)
 {
     buffer->buffer[0] = '\0';
@@ -801,6 +810,10 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w
             reg_maps->vocp = 1;
             break;
 
             reg_maps->vocp = 1;
             break;
 
+        case WINED3DSPR_SAMPLEMASK:
+            reg_maps->sample_mask = 1;
+            break;
+
         default:
             TRACE("Not recording register of type %#x and [%#x][%#x].\n",
                     reg->type, reg->idx[0].offset, reg->idx[1].offset);
         default:
             TRACE("Not recording register of type %#x and [%#x][%#x].\n",
                     reg->type, reg->idx[0].offset, reg->idx[1].offset);
@@ -983,13 +996,49 @@ static void wined3d_insert_interpolation_mode(DWORD *packed_interpolation_mode,
             register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT, mode);
 }
 
             register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT, mode);
 }
 
+static HRESULT shader_scan_output_signature(struct wined3d_shader *shader)
+{
+    const struct wined3d_shader_signature *output_signature = &shader->output_signature;
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    unsigned int i;
+    HRESULT hr;
+
+    for (i = 0; i < output_signature->element_count; ++i)
+    {
+        const struct wined3d_shader_signature_element *e = &output_signature->elements[i];
+        unsigned int mask;
+
+        reg_maps->output_registers |= 1u << e->register_idx;
+        if (e->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
+        {
+            if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask)))
+                return hr;
+            reg_maps->clip_distance_mask |= mask;
+        }
+        else if (e->sysval_semantic == WINED3D_SV_CULL_DISTANCE)
+        {
+            if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask)))
+                return hr;
+            reg_maps->cull_distance_mask |= mask;
+        }
+        else if (e->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX)
+        {
+            reg_maps->viewport_array = 1;
+        }
+    }
+
+    return WINED3D_OK;
+}
+
 /* Note that this does not count the loop register as an address register. */
 /* Note that this does not count the loop register as an address register. */
-static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe,
-        struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature *input_signature,
-        struct wined3d_shader_signature *output_signature, DWORD constf_size)
+static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD constf_size)
 {
     struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT];
 {
     struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT];
+    struct wined3d_shader_signature *output_signature = &shader->output_signature;
+    struct wined3d_shader_signature *input_signature = &shader->input_signature;
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_shader_frontend *fe = shader->frontend;
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     struct wined3d_shader_version shader_version;
     struct wined3d_shader_phase *phase = NULL;
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     struct wined3d_shader_version shader_version;
     struct wined3d_shader_phase *phase = NULL;
@@ -1667,7 +1716,8 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                 shader_record_sample(reg_maps, ins.src[2].reg.idx[0].offset,
                         ins.src[3].reg.idx[0].offset, reg_maps->sampler_map.count);
             }
                 shader_record_sample(reg_maps, ins.src[2].reg.idx[0].offset,
                         ins.src[3].reg.idx[0].offset, reg_maps->sampler_map.count);
             }
-            else if (ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE)
+            else if ((ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE)
+                    || (ins.handler_idx == WINED3DSIH_SAMPLE_INFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE))
             {
                 shader_record_sample(reg_maps, ins.src[0].reg.idx[0].offset,
                         WINED3D_SAMPLER_DEFAULT, reg_maps->sampler_map.count);
             {
                 shader_record_sample(reg_maps, ins.src[0].reg.idx[0].offset,
                         WINED3D_SAMPLER_DEFAULT, reg_maps->sampler_map.count);
@@ -1780,25 +1830,8 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
 
     if (output_signature->elements)
     {
 
     if (output_signature->elements)
     {
-        for (i = 0; i < output_signature->element_count; ++i)
-        {
-            const struct wined3d_shader_signature_element *e = &output_signature->elements[i];
-            unsigned int mask;
-
-            reg_maps->output_registers |= 1u << e->register_idx;
-            if (e->sysval_semantic == WINED3D_SV_CLIP_DISTANCE)
-            {
-                if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask)))
-                    return hr;
-                reg_maps->clip_distance_mask |= mask;
-            }
-            else if (e->sysval_semantic == WINED3D_SV_CULL_DISTANCE)
-            {
-                if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask)))
-                    return hr;
-                reg_maps->cull_distance_mask |= mask;
-            }
-        }
+        if (FAILED(hr = shader_scan_output_signature(shader)))
+            return hr;
     }
     else if (reg_maps->output_registers)
     {
     }
     else if (reg_maps->output_registers)
     {
@@ -1889,6 +1922,23 @@ static void shader_dump_sync_flags(struct wined3d_string_buffer *buffer, DWORD s
         shader_addline(buffer, "_unknown_flags(%#x)", sync_flags);
 }
 
         shader_addline(buffer, "_unknown_flags(%#x)", sync_flags);
 }
 
+static void shader_dump_precise_flags(struct wined3d_string_buffer *buffer, DWORD flags)
+{
+    if (!(flags & WINED3DSI_PRECISE_XYZW))
+        return;
+
+    shader_addline(buffer, " [precise");
+    if (flags != WINED3DSI_PRECISE_XYZW)
+    {
+        shader_addline(buffer, "(%s%s%s%s)",
+                flags & WINED3DSI_PRECISE_X ? "x" : "",
+                flags & WINED3DSI_PRECISE_Y ? "y" : "",
+                flags & WINED3DSI_PRECISE_Z ? "z" : "",
+                flags & WINED3DSI_PRECISE_W ? "w" : "");
+    }
+    shader_addline(buffer, "]");
+}
+
 static void shader_dump_uav_flags(struct wined3d_string_buffer *buffer, DWORD uav_flags)
 {
     if (uav_flags & WINED3DSUF_GLOBALLY_COHERENT)
 static void shader_dump_uav_flags(struct wined3d_string_buffer *buffer, DWORD uav_flags)
 {
     if (uav_flags & WINED3DSUF_GLOBALLY_COHERENT)
@@ -2291,6 +2341,10 @@ static void shader_dump_register(struct wined3d_string_buffer *buffer,
             shader_addline(buffer, "null");
             break;
 
             shader_addline(buffer, "null");
             break;
 
+        case WINED3DSPR_RASTERIZER:
+            shader_addline(buffer, "rasterizer");
+            break;
+
         case WINED3DSPR_RESOURCE:
             shader_addline(buffer, "t");
             break;
         case WINED3DSPR_RESOURCE:
             shader_addline(buffer, "t");
             break;
@@ -3052,6 +3106,10 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
             {
                 shader_dump_sync_flags(&buffer, ins.flags);
             }
             {
                 shader_dump_sync_flags(&buffer, ins.flags);
             }
+            else
+            {
+                shader_dump_precise_flags(&buffer, ins.flags);
+            }
 
             if (wined3d_shader_instruction_has_texel_offset(&ins))
                 shader_addline(&buffer, "(%d,%d,%d)", ins.texel_offset.u, ins.texel_offset.v, ins.texel_offset.w);
 
             if (wined3d_shader_instruction_has_texel_offset(&ins))
                 shader_addline(&buffer, "(%d,%d,%d)", ins.texel_offset.u, ins.texel_offset.v, ins.texel_offset.w);
@@ -3266,11 +3324,11 @@ const struct wined3d_shader_backend_ops none_shader_backend =
 static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_const_count,
         enum wined3d_shader_type type, unsigned int max_version)
 {
 static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_const_count,
         enum wined3d_shader_type type, unsigned int max_version)
 {
+    const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     const struct wined3d_shader_frontend *fe;
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     const struct wined3d_shader_frontend *fe;
-    HRESULT hr;
     unsigned int backend_version;
     unsigned int backend_version;
-    const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
+    HRESULT hr;
 
     TRACE("shader %p, float_const_count %u, type %#x, max_version %u.\n",
             shader, float_const_count, type, max_version);
 
     TRACE("shader %p, float_const_count %u, type %#x, max_version %u.\n",
             shader, float_const_count, type, max_version);
@@ -3288,8 +3346,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_co
         shader_trace_init(fe, shader->frontend_data);
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
         shader_trace_init(fe, shader->frontend_data);
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
-    if (FAILED(hr = shader_get_registers_used(shader, fe, reg_maps, &shader->input_signature,
-            &shader->output_signature, float_const_count)))
+    if (FAILED(hr = shader_get_registers_used(shader, float_const_count)))
         return hr;
 
     if (reg_maps->shader_version.type != type)
         return hr;
 
     if (reg_maps->shader_version.type != type)
@@ -3591,9 +3648,6 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
     TRACE("byte_code %p, byte_code_size %#lx, format %#x, max_version %#x.\n",
             desc->byte_code, (long)desc->byte_code_size, desc->format, desc->max_version);
 
     TRACE("byte_code %p, byte_code_size %#lx, format %#x, max_version %#x.\n",
             desc->byte_code, (long)desc->byte_code_size, desc->format, desc->max_version);
 
-    if (!desc->byte_code)
-        return WINED3DERR_INVALIDCALL;
-
     if (!(shader->frontend = shader_select_frontend(desc->format)))
     {
         FIXME("Unable to find frontend for shader.\n");
     if (!(shader->frontend = shader_select_frontend(desc->format)))
     {
         FIXME("Unable to find frontend for shader.\n");
@@ -3668,25 +3722,39 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
         byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
     }
 
         byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
     }
 
-    if (!(shader->function = heap_alloc(byte_code_size)))
+    if (desc->byte_code && byte_code_size)
     {
     {
-        shader_cleanup(shader);
-        return E_OUTOFMEMORY;
-    }
-    memcpy(shader->function, desc->byte_code, byte_code_size);
-    shader->functionLength = byte_code_size;
+        if (!(shader->function = heap_alloc(byte_code_size)))
+        {
+            shader_cleanup(shader);
+            return E_OUTOFMEMORY;
+        }
+        memcpy(shader->function, desc->byte_code, byte_code_size);
+        shader->functionLength = byte_code_size;
 
 
-    if (FAILED(hr = shader_set_function(shader, float_const_count, type, desc->max_version)))
+        if (FAILED(hr = shader_set_function(shader, float_const_count, type, desc->max_version)))
+        {
+            WARN("Failed to set function, hr %#x.\n", hr);
+            shader_cleanup(shader);
+            return hr;
+        }
+    }
+    else
     {
     {
-        WARN("Failed to set function, hr %#x.\n", hr);
-        shader_cleanup(shader);
-        return hr;
+        shader->reg_maps.shader_version.type = type;
+        shader->reg_maps.shader_version.major = 4;
+        shader->reg_maps.shader_version.minor = 0;
+        shader_set_limits(shader);
+
+        if (FAILED(hr = shader_scan_output_signature(shader)))
+        {
+            shader_cleanup(shader);
+            return hr;
+        }
     }
 
     shader->load_local_constsF = shader->lconst_inf_or_nan;
 
     }
 
     shader->load_local_constsF = shader->lconst_inf_or_nan;
 
-    wined3d_cs_init_object(shader->device->cs, wined3d_shader_init_object, shader);
-
     return hr;
 }
 
     return hr;
 }
 
@@ -3723,20 +3791,40 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
         const struct wined3d_shader_desc *desc, const struct wined3d_stream_output_desc *so_desc,
         void *parent, const struct wined3d_parent_ops *parent_ops)
 {
         const struct wined3d_shader_desc *desc, const struct wined3d_stream_output_desc *so_desc,
         void *parent, const struct wined3d_parent_ops *parent_ops)
 {
-    struct wined3d_stream_output_element *elements = NULL;
+    struct wined3d_shader_desc shader_desc = *desc;
+    struct wined3d_stream_output_element *elements;
+    enum wined3d_shader_type shader_type;
     HRESULT hr;
 
     HRESULT hr;
 
-    if (so_desc && !(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
-        return E_OUTOFMEMORY;
-
-    if (FAILED(hr = shader_init(shader, device, desc, 0, WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops)))
+    if (so_desc)
     {
     {
-        heap_free(elements);
-        return hr;
+        shader_type = shader_get_shader_type(desc);
+        switch (shader_type)
+        {
+            case WINED3D_SHADER_TYPE_VERTEX:
+                shader_desc.byte_code = NULL;
+                shader_desc.byte_code_size = 0;
+                break;
+            case WINED3D_SHADER_TYPE_DOMAIN:
+                FIXME("Stream output not supported for %s.\n", debug_shader_type(shader_type));
+                return E_NOTIMPL;
+            default:
+                break;
+        }
     }
 
     }
 
+    if (FAILED(hr = shader_init(shader, device, &shader_desc, 0,
+            WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops)))
+        return hr;
+
     if (so_desc)
     {
     if (so_desc)
     {
+        if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
+        {
+            shader_cleanup(shader);
+            return E_OUTOFMEMORY;
+        }
+
         shader->u.gs.so_desc = *so_desc;
         shader->u.gs.so_desc.elements = elements;
         memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements));
         shader->u.gs.so_desc = *so_desc;
         shader->u.gs.so_desc.elements = elements;
         memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements));
@@ -3776,6 +3864,9 @@ void find_gs_compile_args(const struct wined3d_state *state, const struct wined3
 
     args->output_count = pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output;
 
 
     args->output_count = pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output;
 
+    if (!(args->primitive_type = shader->u.gs.input_type))
+        args->primitive_type = d3d_primitive_type_from_gl(state->gl_primitive_type);
+
     init_interpolation_compile_args(args->interpolation_mode, pixel_shader, gl_info);
 }
 
     init_interpolation_compile_args(args->interpolation_mode, pixel_shader, gl_info);
 }
 
@@ -3873,8 +3964,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
             switch (texture->target)
             {
                 /* RECT textures are distinguished from 2D textures via np2_fixup */
             switch (texture->target)
             {
                 /* RECT textures are distinguished from 2D textures via np2_fixup */
-                case GL_TEXTURE_RECTANGLE_ARB:
-                case GL_TEXTURE_2D:
+                default:
                     break;
 
                 case GL_TEXTURE_3D:
                     break;
 
                 case GL_TEXTURE_3D:
@@ -3926,16 +4016,16 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
     if (shader->reg_maps.shader_version.major >= 3)
     {
         if (position_transformed)
     if (shader->reg_maps.shader_version.major >= 3)
     {
         if (position_transformed)
-            args->vp_mode = pretransformed;
+            args->vp_mode = WINED3D_VP_MODE_NONE;
         else if (use_vs(state))
         else if (use_vs(state))
-            args->vp_mode = vertexshader;
+            args->vp_mode = WINED3D_VP_MODE_SHADER;
         else
         else
-            args->vp_mode = fixedfunction;
+            args->vp_mode = WINED3D_VP_MODE_FF;
         args->fog = WINED3D_FFP_PS_FOG_OFF;
     }
     else
     {
         args->fog = WINED3D_FFP_PS_FOG_OFF;
     }
     else
     {
-        args->vp_mode = vertexshader;
+        args->vp_mode = WINED3D_VP_MODE_SHADER;
         if (state->render_states[WINED3D_RS_FOGENABLE])
         {
             switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
         if (state->render_states[WINED3D_RS_FOGENABLE])
         {
             switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
@@ -4110,6 +4200,9 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4120,6 +4213,8 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created compute shader %p.\n", object);
     *shader = object;
 
     TRACE("Created compute shader %p.\n", object);
     *shader = object;
 
@@ -4135,6 +4230,9 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4145,6 +4243,8 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created domain shader %p.\n", object);
     *shader = object;
 
     TRACE("Created domain shader %p.\n", object);
     *shader = object;
 
@@ -4161,6 +4261,9 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, so_desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, so_desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, so_desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, so_desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4171,6 +4274,8 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created geometry shader %p.\n", object);
     *shader = object;
 
     TRACE("Created geometry shader %p.\n", object);
     *shader = object;
 
@@ -4186,6 +4291,9 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4196,6 +4304,8 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created hull shader %p.\n", object);
     *shader = object;
 
     TRACE("Created hull shader %p.\n", object);
     *shader = object;
 
@@ -4211,6 +4321,9 @@ HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4221,6 +4334,8 @@ HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created pixel shader %p.\n", object);
     *shader = object;
 
     TRACE("Created pixel shader %p.\n", object);
     *shader = object;
 
@@ -4236,6 +4351,9 @@ HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const stru
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
     TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n",
             device, desc, parent, parent_ops, shader);
 
+    if (!desc->byte_code)
+        return WINED3DERR_INVALIDCALL;
+
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -4246,6 +4364,8 @@ HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const stru
         return hr;
     }
 
         return hr;
     }
 
+    wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
+
     TRACE("Created vertex shader %p.\n", object);
     *shader = object;
 
     TRACE("Created vertex shader %p.\n", object);
     *shader = object;
 
index 8eac746..b119e8f 100644 (file)
@@ -61,6 +61,9 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode);
 #define WINED3D_SM4_GLOBAL_FLAGS_SHIFT          11
 #define WINED3D_SM4_GLOBAL_FLAGS_MASK           (0xffu << WINED3D_SM4_GLOBAL_FLAGS_SHIFT)
 
 #define WINED3D_SM4_GLOBAL_FLAGS_SHIFT          11
 #define WINED3D_SM4_GLOBAL_FLAGS_MASK           (0xffu << WINED3D_SM4_GLOBAL_FLAGS_SHIFT)
 
+#define WINED3D_SM5_PRECISE_SHIFT               19
+#define WINED3D_SM5_PRECISE_MASK                (0xfu << WINED3D_SM5_PRECISE_SHIFT)
+
 #define WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT   11
 #define WINED3D_SM5_CONTROL_POINT_COUNT_MASK    (0xffu << WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT)
 
 #define WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT   11
 #define WINED3D_SM5_CONTROL_POINT_COUNT_MASK    (0xffu << WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT)
 
@@ -315,6 +318,7 @@ enum wined3d_sm4_register_type
     WINED3D_SM4_RT_PRIMID                  = 0x0b,
     WINED3D_SM4_RT_DEPTHOUT                = 0x0c,
     WINED3D_SM4_RT_NULL                    = 0x0d,
     WINED3D_SM4_RT_PRIMID                  = 0x0b,
     WINED3D_SM4_RT_DEPTHOUT                = 0x0c,
     WINED3D_SM4_RT_NULL                    = 0x0d,
+    WINED3D_SM4_RT_RASTERIZER              = 0x0e,
     WINED3D_SM4_RT_OMASK                   = 0x0f,
     WINED3D_SM5_RT_STREAM                  = 0x10,
     WINED3D_SM5_RT_FUNCTION_BODY           = 0x11,
     WINED3D_SM4_RT_OMASK                   = 0x0f,
     WINED3D_SM5_RT_STREAM                  = 0x10,
     WINED3D_SM5_RT_FUNCTION_BODY           = 0x11,
@@ -1129,7 +1133,7 @@ static const enum wined3d_shader_register_type register_type_table[] =
     /* WINED3D_SM4_RT_PRIMID */                  WINED3DSPR_PRIMID,
     /* WINED3D_SM4_RT_DEPTHOUT */                WINED3DSPR_DEPTHOUT,
     /* WINED3D_SM4_RT_NULL */                    WINED3DSPR_NULL,
     /* WINED3D_SM4_RT_PRIMID */                  WINED3DSPR_PRIMID,
     /* WINED3D_SM4_RT_DEPTHOUT */                WINED3DSPR_DEPTHOUT,
     /* WINED3D_SM4_RT_NULL */                    WINED3DSPR_NULL,
-    /* UNKNOWN */                                ~0u,
+    /* WINED3D_SM4_RT_RASTERIZER */              WINED3DSPR_RASTERIZER,
     /* WINED3D_SM4_RT_OMASK */                   WINED3DSPR_SAMPLEMASK,
     /* WINED3D_SM5_RT_STREAM */                  WINED3DSPR_STREAM,
     /* WINED3D_SM5_RT_FUNCTION_BODY */           WINED3DSPR_FUNCTIONBODY,
     /* WINED3D_SM4_RT_OMASK */                   WINED3DSPR_SAMPLEMASK,
     /* WINED3D_SM5_RT_STREAM */                  WINED3DSPR_STREAM,
     /* WINED3D_SM5_RT_FUNCTION_BODY */           WINED3DSPR_FUNCTIONBODY,
@@ -1218,6 +1222,43 @@ static enum wined3d_data_type map_data_type(char t)
     }
 }
 
     }
 }
 
+enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code, size_t byte_code_size)
+{
+    DWORD shader_type;
+
+    if (byte_code_size / sizeof(*byte_code) < 1)
+    {
+        WARN("Invalid byte code size %lu.\n", (long)byte_code_size);
+        return WINED3D_SHADER_TYPE_INVALID;
+    }
+
+    shader_type = byte_code[0] >> 16;
+    switch (shader_type)
+    {
+        case WINED3D_SM4_PS:
+            return WINED3D_SHADER_TYPE_PIXEL;
+            break;
+        case WINED3D_SM4_VS:
+            return WINED3D_SHADER_TYPE_VERTEX;
+            break;
+        case WINED3D_SM4_GS:
+            return WINED3D_SHADER_TYPE_GEOMETRY;
+            break;
+        case WINED3D_SM5_HS:
+            return WINED3D_SHADER_TYPE_HULL;
+            break;
+        case WINED3D_SM5_DS:
+            return WINED3D_SHADER_TYPE_DOMAIN;
+            break;
+        case WINED3D_SM5_CS:
+            return WINED3D_SHADER_TYPE_COMPUTE;
+            break;
+        default:
+            FIXME("Unrecognised shader type %#x.\n", shader_type);
+            return WINED3D_SHADER_TYPE_INVALID;
+    }
+}
+
 static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
         const struct wined3d_shader_signature *output_signature)
 {
 static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
         const struct wined3d_shader_signature *output_signature)
 {
@@ -1251,35 +1292,13 @@ static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
     priv->start = &byte_code[2];
     priv->end = &byte_code[token_count];
 
     priv->start = &byte_code[2];
     priv->end = &byte_code[token_count];
 
-    switch (version_token >> 16)
+    priv->shader_version.type = wined3d_get_sm4_shader_type(byte_code, byte_code_size);
+    if (priv->shader_version.type == WINED3D_SHADER_TYPE_INVALID)
     {
     {
-        case WINED3D_SM4_PS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
-            break;
-
-        case WINED3D_SM4_VS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
-            break;
-
-        case WINED3D_SM4_GS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY;
-            break;
-
-        case WINED3D_SM5_HS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_HULL;
-            break;
-
-        case WINED3D_SM5_DS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_DOMAIN;
-            break;
-
-        case WINED3D_SM5_CS:
-            priv->shader_version.type = WINED3D_SHADER_TYPE_COMPUTE;
-            break;
-
-        default:
-            FIXME("Unrecognised shader type %#x.\n", version_token >> 16);
+        heap_free(priv);
+        return NULL;
     }
     }
+
     priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token);
     priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token);
 
     priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token);
     priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token);
 
@@ -1628,6 +1647,7 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi
     unsigned int i, len;
     SIZE_T remaining;
     const DWORD *p;
     unsigned int i, len;
     SIZE_T remaining;
     const DWORD *p;
+    DWORD precise;
 
     list_move_head(&priv->src_free, &priv->src);
 
 
     list_move_head(&priv->src_free, &priv->src);
 
@@ -1702,12 +1722,13 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi
             shader_sm4_read_instruction_modifier(previous_token = *p++, ins);
 
         ins->flags = (opcode_token & WINED3D_SM4_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT;
             shader_sm4_read_instruction_modifier(previous_token = *p++, ins);
 
         ins->flags = (opcode_token & WINED3D_SM4_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT;
-
         if (ins->flags & WINED3D_SM4_INSTRUCTION_FLAG_SATURATE)
         {
             ins->flags &= ~WINED3D_SM4_INSTRUCTION_FLAG_SATURATE;
             instruction_dst_modifier = WINED3DSPDM_SATURATE;
         }
         if (ins->flags & WINED3D_SM4_INSTRUCTION_FLAG_SATURATE)
         {
             ins->flags &= ~WINED3D_SM4_INSTRUCTION_FLAG_SATURATE;
             instruction_dst_modifier = WINED3DSPDM_SATURATE;
         }
+        precise = (opcode_token & WINED3D_SM5_PRECISE_MASK) >> WINED3D_SM5_PRECISE_SHIFT;
+        ins->flags |= precise << WINED3DSI_PRECISE_SHIFT;
 
         for (i = 0; i < ins->dst_count; ++i)
         {
 
         for (i = 0; i < ins->dst_count; ++i)
         {
index 2f506c3..1bd3863 100644 (file)
@@ -36,7 +36,6 @@
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
-WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
 
 ULONG CDECL wined3d_blend_state_incref(struct wined3d_blend_state *state)
 {
 
 ULONG CDECL wined3d_blend_state_incref(struct wined3d_blend_state *state)
 {
@@ -1014,7 +1013,7 @@ static void state_stencil(struct wined3d_context *context, const struct wined3d_
     }
 }
 
     }
 }
 
-static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void state_stencilwrite2s_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
     const struct wined3d_gl_info *gl_info = context->gl_info;
 {
     DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -1831,28 +1830,6 @@ static void state_depthbias(struct wined3d_context *context, const struct wined3
     checkGLcall("depth bias");
 }
 
     checkGLcall("depth bias");
 }
 
-static void state_depthclip(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-
-    if (state->render_states[WINED3D_RS_DEPTHCLIP])
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP);
-        checkGLcall("glDisable(GL_DEPTH_CLAMP)");
-    }
-    else
-    {
-        gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP);
-        checkGLcall("glEnable(GL_DEPTH_CLAMP)");
-    }
-}
-
-static void state_depthclip_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    if (!state->render_states[WINED3D_RS_DEPTHCLIP])
-        FIXME("Depth clamping not supported by GL.\n");
-}
-
 static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     if (state->render_states[WINED3D_RS_ZVISIBLE])
 static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     if (state->render_states[WINED3D_RS_ZVISIBLE])
@@ -3334,76 +3311,6 @@ static void transform_texture(struct wined3d_context *context, const struct wine
     checkGLcall("glLoadMatrixf");
 }
 
     checkGLcall("glLoadMatrixf");
 }
 
-static void unload_tex_coords(const struct wined3d_gl_info *gl_info)
-{
-    unsigned int texture_idx;
-
-    for (texture_idx = 0; texture_idx < gl_info->limits.texture_coords; ++texture_idx)
-    {
-        GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
-        gl_info->gl_ops.gl.p_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    }
-}
-
-static void load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si,
-        GLuint *curVBO, const struct wined3d_state *state)
-{
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    unsigned int mapped_stage = 0;
-    unsigned int textureNo;
-
-    for (textureNo = 0; textureNo < context->d3d_info->limits.ffp_blend_stages; ++textureNo)
-    {
-        int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
-
-        mapped_stage = context->tex_unit_map[textureNo];
-        if (mapped_stage == 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 (coordIdx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
-        {
-            const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
-
-            TRACE("Setting up texture %u, idx %d, coordindx %u, data {%#x:%p}.\n",
-                    textureNo, mapped_stage, coordIdx, e->data.buffer_object, e->data.addr);
-
-            if (*curVBO != e->data.buffer_object)
-            {
-                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-                checkGLcall("glBindBuffer");
-                *curVBO = 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 (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo)
-        {
-            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
-        }
-    }
-
-    checkGLcall("loadTexCoords");
-}
-
 static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
 static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
@@ -3574,8 +3481,8 @@ static void tex_coordindex(struct wined3d_context *context, const struct wined3d
          */
         GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
 
          */
         GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
 
-        unload_tex_coords(gl_info);
-        load_tex_coords(context, &context->stream_info, &curVBO, state);
+        context_unload_tex_coords(context);
+        context_load_tex_coords(context, &context->stream_info, &curVBO, state);
     }
 }
 
     }
 }
 
@@ -3865,41 +3772,9 @@ void clipplane(struct wined3d_context *context, const struct wined3d_state *stat
 
 static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
 
 static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    UINT matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    GLenum glMat;
-
-    TRACE("Setting world matrix %d\n", matrix);
-
-    if (matrix >= gl_info->limits.blends)
-    {
-        WARN("Unsupported blend matrix set\n");
-        return;
-    }
-
-    if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)))
-        return;
-
-    /* GL_MODELVIEW0_ARB:  0x1700
-     * GL_MODELVIEW1_ARB:  0x850a
-     * GL_MODELVIEW2_ARB:  0x8722
-     * GL_MODELVIEW3_ARB:  0x8723
-     * etc
-     * GL_MODELVIEW31_ARB: 0x873f
-     */
-    if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
-    else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
-
-    gl_info->gl_ops.gl.p_glMatrixMode(glMat);
-    checkGLcall("glMatrixMode(glMat)");
+    unsigned int matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
 
 
-    /* World matrix 0 is multiplied with the view matrix because d3d uses 3
-     * matrices while gl uses only 2. To avoid weighting the view matrix
-     * incorrectly it has to be multiplied into every GL modelview matrix. */
-    gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
-    checkGLcall("glLoadMatrixf");
-    gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)]._11);
-    checkGLcall("glMultMatrixf");
+    WARN("Unsupported world matrix %u set.\n", matrix);
 }
 
 static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 }
 
 static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -3914,50 +3789,6 @@ static void state_vertexblend_w(struct wined3d_context *context, const struct wi
     else WARN("Vertex blend flags %#x not supported.\n", f);
 }
 
     else WARN("Vertex blend flags %#x not supported.\n", f);
 }
 
-static void state_vertexblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    enum wined3d_vertex_blend_flags val = state->render_states[WINED3D_RS_VERTEXBLEND];
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_device *device = context->device;
-    static unsigned int once;
-
-    switch (val)
-    {
-        case WINED3D_VBF_1WEIGHTS:
-        case WINED3D_VBF_2WEIGHTS:
-        case WINED3D_VBF_3WEIGHTS:
-            gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_BLEND_ARB);
-            checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
-
-            /* D3D adds one more matrix which has weight (1 - sum(weights)).
-             * This is enabled at context creation with enabling
-             * GL_WEIGHT_SUM_UNITY_ARB. */
-            GL_EXTCALL(glVertexBlendARB(state->render_states[WINED3D_RS_VERTEXBLEND] + 1));
-
-            if (!device->vertexBlendUsed)
-            {
-                unsigned int i;
-                for (i = 1; i < gl_info->limits.blends; ++i)
-                {
-                    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i))))
-                        transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i)));
-                }
-                device->vertexBlendUsed = TRUE;
-            }
-            break;
-
-        case WINED3D_VBF_TWEENING:
-        case WINED3D_VBF_0WEIGHTS: /* Indexed vertex blending, not supported. */
-            if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val);
-            else WARN("Vertex blend flags %#x not supported.\n", val);
-            /* Fall through. */
-        case WINED3D_VBF_DISABLE:
-            gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_BLEND_ARB);
-            checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
-            break;
-    }
-}
-
 static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -4008,16 +3839,6 @@ static void transform_view(struct wined3d_context *context, const struct wined3d
      * No need to do it here if the state is scheduled for update. */
     if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
         transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
      * No need to do it here if the state is scheduled for update. */
     if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
         transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
-
-    /* Avoid looping over a number of matrices if the app never used the functionality */
-    if (context->device->vertexBlendUsed)
-    {
-        for (k = 1; k < gl_info->limits.blends; ++k)
-        {
-            if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k))))
-                transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k)));
-        }
-    }
 }
 
 static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 }
 
 static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -4033,518 +3854,18 @@ static void transform_projection(struct wined3d_context *context, const struct w
     checkGLcall("glLoadMatrixf");
 }
 
     checkGLcall("glLoadMatrixf");
 }
 
-/* This should match any arrays loaded in load_vertex_data.
- * TODO: Only load / unload arrays if we have to. */
-static void unload_vertex_data(const struct wined3d_gl_info *gl_info)
-{
-    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);
-    if (gl_info->supported[ARB_VERTEX_BLEND])
-        gl_info->gl_ops.gl.p_glDisableClientState(GL_WEIGHT_ARRAY_ARB);
-    unload_tex_coords(gl_info);
-}
-
-static inline void unload_numbered_array(struct wined3d_context *context, 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);
-}
-
-/* This should match any arrays loaded in loadNumberedArrays
- * TODO: Only load / unload arrays if we have to. */
-static void unload_numbered_arrays(struct wined3d_context *context)
-{
-    /* disable any attribs (this is the same for both GLSL and ARB modes) */
-    int i;
-
-    for (i = 0; i < context->gl_info->limits.vertex_attribs; ++i) {
-        unload_numbered_array(context, i);
-    }
-}
-
-static void 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 curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
-    unsigned int i;
-
-    /* Default to no instancing */
-    context->instance_count = 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))
-                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))
-                unload_numbered_array(context, i);
-            continue;
-        }
-
-        TRACE_(d3d_shader)("Loading array %u [VBO=%u].\n", i, element->data.buffer_object);
-
-        if (element->stride)
-        {
-            if (curVBO != element->data.buffer_object)
-            {
-                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, element->data.buffer_object));
-                checkGLcall("glBindBuffer");
-                curVBO = 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
-             * curVBO 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))
-                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");
-}
-
-static void 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;
-    GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
-    const struct wined3d_stream_info_element *e;
-
-    TRACE("Using fast vertex array code\n");
-
-    /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
-    context->instance_count = 0;
-
-    /* Blend Data ---------------------------------------------- */
-    if ((si->use_map & (1u << WINED3D_FFP_BLENDWEIGHT))
-            || si->use_map & (1u << WINED3D_FFP_BLENDINDICES))
-    {
-        e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
-
-        if (gl_info->supported[ARB_VERTEX_BLEND])
-        {
-            TRACE("Blend %u %p %u\n", e->format->component_count,
-                    e->data.addr + state->load_base_vertex_index * e->stride, e->stride);
-
-            gl_info->gl_ops.gl.p_glEnableClientState(GL_WEIGHT_ARRAY_ARB);
-            checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
-
-            GL_EXTCALL(glVertexBlendARB(e->format->component_count + 1));
-
-            if (curVBO != e->data.buffer_object)
-            {
-                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-                checkGLcall("glBindBuffer");
-                curVBO = e->data.buffer_object;
-            }
-
-            TRACE("glWeightPointerARB(%#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_EXTCALL(glWeightPointerARB(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
-                    e->data.addr + state->load_base_vertex_index * e->stride));
-
-            checkGLcall("glWeightPointerARB");
-
-            if (si->use_map & (1u << WINED3D_FFP_BLENDINDICES))
-            {
-                static BOOL warned;
-                if (!warned)
-                {
-                    FIXME("blendMatrixIndices support\n");
-                    warned = TRUE;
-                }
-            }
-        }
-        else
-        {
-            /* 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");
-        }
-    }
-    else
-    {
-        if (gl_info->supported[ARB_VERTEX_BLEND])
-        {
-            static const GLbyte one = 1;
-            GL_EXTCALL(glWeightbvARB(1, &one));
-            checkGLcall("glWeightbvARB(gl_info->max_blends, weights)");
-        }
-    }
-
-    /* Point Size ----------------------------------------------*/
-    if (si->use_map & (1u << WINED3D_FFP_PSIZE))
-    {
-        /* no such functionality in the fixed function GL pipeline */
-        TRACE("Cannot change ptSize here in openGl\n");
-        /* TODO: Implement this function in using shaders if they are available */
-    }
-
-    /* Vertex Pointers -----------------------------------------*/
-    if (si->use_map & (1u << WINED3D_FFP_POSITION))
-    {
-        e = &si->elements[WINED3D_FFP_POSITION];
-
-        if (curVBO != e->data.buffer_object)
-        {
-            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-            checkGLcall("glBindBuffer");
-            curVBO = 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 (curVBO != e->data.buffer_object)
-        {
-            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-            checkGLcall("glBindBuffer");
-            curVBO = 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 (curVBO != e->data.buffer_object)
-        {
-            GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-            checkGLcall("glBindBuffer");
-            curVBO = 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 (curVBO != e->data.buffer_object)
-            {
-                GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object));
-                checkGLcall("glBindBuffer");
-                curVBO = 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 color pointers for type %x\n", type);
-                        /* Make sure that the right color 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 coords -------------------------------------------*/
-    load_tex_coords(context, si, &curVBO, state);
-}
-
 static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
 static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    BOOL load_numbered = context->d3d_info->ffp_generic_attributes
-            || (use_vs(state) && !context->use_immediate_mode_draw);
-    BOOL load_named = !context->d3d_info->ffp_generic_attributes
-            && !use_vs(state) && !context->use_immediate_mode_draw;
-
-    if (isStateDirty(context, STATE_VDECL)) return;
-    if (context->numberedArraysLoaded && !load_numbered)
-    {
-        unload_numbered_arrays(context);
-        context->numberedArraysLoaded = FALSE;
-        context->numbered_array_mask = 0;
-    }
-    else if (context->namedArraysLoaded)
-    {
-        unload_vertex_data(context->gl_info);
-        context->namedArraysLoaded = FALSE;
-    }
-
-    if (load_numbered)
-    {
-        TRACE("Loading numbered arrays\n");
-        load_numbered_arrays(context, &context->stream_info, state);
-        context->numberedArraysLoaded = TRUE;
-    }
-    else if (load_named)
-    {
-        TRACE("Loading vertex data\n");
-        load_vertex_data(context, &context->stream_info, state);
-        context->namedArraysLoaded = TRUE;
-    }
+    if (isStateDirty(context, STATE_VDECL))
+        return;
+    context_update_stream_sources(context, state);
 }
 
 static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     if (isStateDirty(context, STATE_STREAMSRC))
         return;
 }
 
 static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     if (isStateDirty(context, STATE_STREAMSRC))
         return;
-    streamsrc(context, state, STATE_STREAMSRC);
+    context_update_stream_sources(context, state);
 }
 
 static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 }
 
 static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -4682,30 +4003,18 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     }
 }
 
     }
 }
 
-static void get_viewport(struct wined3d_context *context, const struct wined3d_state *state,
-        struct wined3d_viewport *viewport)
+static void get_viewports(struct wined3d_context *context, const struct wined3d_state *state,
+        unsigned int viewport_count, struct wined3d_viewport *viewports)
 {
     const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil;
     const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
 {
     const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil;
     const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
-    unsigned int width, height;
+    unsigned int width, height, i;
 
 
-    *viewport = state->viewport;
-
-    if (target)
-    {
-        if (context->d3d_info->wined3d_creation_flags & WINED3D_LIMIT_VIEWPORT)
-        {
-            if (viewport->width > target->width)
-                viewport->width = target->width;
-            if (viewport->height > target->height)
-                viewport->height = target->height;
-        }
-    }
+    for (i = 0; i < viewport_count; ++i)
+        viewports[i] = state->viewports[i];
 
 
-    /*
-     * Note: GL requires lower left, DirectX supplies upper left. This is
-     * reversed when using offscreen rendering.
-     */
+    /* Note: GL uses a lower left origin while DirectX uses upper left. This
+     * is reversed when using offscreen rendering. */
     if (context->render_offscreen)
         return;
 
     if (context->render_offscreen)
         return;
 
@@ -4723,22 +4032,53 @@ static void get_viewport(struct wined3d_context *context, const struct wined3d_s
         return;
     }
 
         return;
     }
 
-    viewport->y = height - (viewport->y + viewport->height);
+    for (i = 0; i < viewport_count; ++i)
+        viewports[i].y = height - (viewports[i].y + viewports[i].height);
 }
 
 static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 }
 
 static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_viewport vp;
+    struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];
 
 
-    get_viewport(context, state, &vp);
+    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+    {
+        GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS];
+        GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS];
 
 
-    gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+        unsigned int i, reset_count = 0;
 
 
-    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
-        GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height));
+        get_viewports(context, state, state->viewport_count, vp);
+        for (i = 0; i < state->viewport_count; ++i)
+        {
+            depth_ranges[i * 2]     = vp[i].min_z;
+            depth_ranges[i * 2 + 1] = vp[i].max_z;
+
+            viewports[i * 4]     = vp[i].x;
+            viewports[i * 4 + 1] = vp[i].y;
+            viewports[i * 4 + 2] = vp[i].width;
+            viewports[i * 4 + 3] = vp[i].height;
+        }
+
+        if (context->viewport_count > state->viewport_count)
+            reset_count = context->viewport_count - state->viewport_count;
+
+        if (reset_count)
+        {
+            memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges));
+            memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports));
+        }
+
+        GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges));
+        GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports));
+        context->viewport_count = state->viewport_count;
+    }
     else
     else
-        gl_info->gl_ops.gl.p_glViewport(vp.x, vp.y, vp.width, vp.height);
+    {
+        get_viewports(context, state, 1, vp);
+        gl_info->gl_ops.gl.p_glDepthRange(vp[0].min_z, vp[0].max_z);
+        gl_info->gl_ops.gl.p_glViewport(vp[0].x, vp[0].y, vp[0].width, vp[0].height);
+    }
     checkGLcall("setting clip space and viewport");
 }
 
     checkGLcall("setting clip space and viewport");
 }
 
@@ -4749,16 +4089,39 @@ static void viewport_miscpart_cc(struct wined3d_context *context,
     float pixel_center_offset = context->d3d_info->wined3d_creation_flags
             & WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     float pixel_center_offset = context->d3d_info->wined3d_creation_flags
             & WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_viewport vp;
-
-    get_viewport(context, state, &vp);
-    vp.x += pixel_center_offset;
-    vp.y += pixel_center_offset;
+    struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];
+    GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS];
+    GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS];
+    unsigned int i, reset_count = 0;
 
 
-    gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+    get_viewports(context, state, state->viewport_count, vp);
 
     GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE));
 
     GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE));
-    GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height));
+
+    for (i = 0; i < state->viewport_count; ++i)
+    {
+        depth_ranges[i * 2]     = vp[i].min_z;
+        depth_ranges[i * 2 + 1] = vp[i].max_z;
+
+        viewports[i * 4] = vp[i].x + pixel_center_offset;
+        viewports[i * 4 + 1] = vp[i].y + pixel_center_offset;
+        viewports[i * 4 + 2] = vp[i].width;
+        viewports[i * 4 + 3] = vp[i].height;
+    }
+
+    if (context->viewport_count > state->viewport_count)
+        reset_count = context->viewport_count - state->viewport_count;
+
+    if (reset_count)
+    {
+        memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges));
+        memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports));
+    }
+
+    GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges));
+    GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports));
+    context->viewport_count = state->viewport_count;
+
     checkGLcall("setting clip space and viewport");
 }
 
     checkGLcall("setting clip space and viewport");
 }
 
@@ -4899,27 +4262,53 @@ static void light(struct wined3d_context *context, const struct wined3d_state *s
 static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    const RECT *r = &state->scissor_rect;
+    unsigned int height = 0;
+    const RECT *r;
 
     /* Warning: glScissor uses window coordinates, not viewport coordinates,
      * so our viewport correction does not apply. Warning2: Even in windowed
      * mode the coords are relative to the window, not the screen. */
 
     /* Warning: glScissor uses window coordinates, not viewport coordinates,
      * so our viewport correction does not apply. Warning2: Even in windowed
      * mode the coords are relative to the window, not the screen. */
-    TRACE("Setting new scissor rect to %s.\n", wine_dbgstr_rect(r));
 
 
-    if (context->render_offscreen)
-    {
-        gl_info->gl_ops.gl.p_glScissor(r->left, r->top, r->right - r->left, r->bottom - r->top);
-    }
-    else
+    if (!context->render_offscreen)
     {
         const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
     {
         const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
-        UINT height;
-        UINT width;
+        unsigned int width;
 
         wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
 
         wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
-        gl_info->gl_ops.gl.p_glScissor(r->left, height - r->bottom, r->right - r->left, r->bottom - r->top);
     }
     }
-    checkGLcall("glScissor");
+
+    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+    {
+        GLint sr[4 * WINED3D_MAX_VIEWPORTS];
+        unsigned int i, reset_count = 0;
+
+        for (i = 0; i < state->scissor_rect_count; ++i)
+        {
+            r = &state->scissor_rects[i];
+
+            sr[i * 4] = r->left;
+            sr[i * 4 + 1] = height ? height - r->top : r->top;
+            sr[i * 4 + 2] = r->right - r->left;
+            sr[i * 4 + 3] = r->bottom - r->top;
+        }
+
+        if (context->scissor_rect_count > state->scissor_rect_count)
+            reset_count = context->scissor_rect_count - state->scissor_rect_count;
+
+        if (reset_count)
+            memset(&sr[state->scissor_rect_count * 4], 0, reset_count * 4 * sizeof(GLint));
+
+        GL_EXTCALL(glScissorArrayv(0, state->scissor_rect_count + reset_count, sr));
+        checkGLcall("glScissorArrayv");
+        context->scissor_rect_count = state->scissor_rect_count;
+    }
+    else
+    {
+        r = &state->scissor_rects[0];
+        gl_info->gl_ops.gl.p_glScissor(r->left, height ? height - r->top : r->top,
+                r->right - r->left, r->bottom - r->top);
+        checkGLcall("glScissor");
+    }
 }
 
 static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 }
 
 static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -4938,7 +4327,23 @@ static void indexbuffer(struct wined3d_context *context, const struct wined3d_st
     }
 }
 
     }
 }
 
-static void frontface(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void depth_clip(const struct wined3d_rasterizer_state *r, const struct wined3d_gl_info *gl_info)
+{
+    if (!gl_info->supported[ARB_DEPTH_CLAMP])
+    {
+        if (r && !r->desc.depth_clip)
+            FIXME("Depth clamp not supported by this GL implementation.\n");
+        return;
+    }
+
+    if (r && !r->desc.depth_clip)
+        gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP);
+    checkGLcall("depth clip");
+}
+
+static void rasterizer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum mode;
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum mode;
@@ -4949,9 +4354,10 @@ static void frontface(struct wined3d_context *context, const struct wined3d_stat
 
     gl_info->gl_ops.gl.p_glFrontFace(mode);
     checkGLcall("glFrontFace");
 
     gl_info->gl_ops.gl.p_glFrontFace(mode);
     checkGLcall("glFrontFace");
+    depth_clip(state->rasterizer_state, gl_info);
 }
 
 }
 
-static void frontface_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void rasterizer_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum mode;
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum mode;
@@ -4960,6 +4366,7 @@ static void frontface_cc(struct wined3d_context *context, const struct wined3d_s
 
     gl_info->gl_ops.gl.p_glFrontFace(mode);
     checkGLcall("glFrontFace");
 
     gl_info->gl_ops.gl.p_glFrontFace(mode);
     checkGLcall("glFrontFace");
+    depth_clip(state->rasterizer_state, gl_info);
 }
 
 static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 }
 
 static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -5129,8 +4536,8 @@ const struct StateEntryTemplate misc_state_template[] =
     { STATE_BLEND,                                        { STATE_BLEND,                                        state_blend_object  }, WINED3D_GL_EXT_NONE             },
     { STATE_STREAMSRC,                                    { STATE_STREAMSRC,                                    streamsrc           }, WINED3D_GL_EXT_NONE             },
     { STATE_VDECL,                                        { STATE_VDECL,                                        vdecl_miscpart      }, WINED3D_GL_EXT_NONE             },
     { STATE_BLEND,                                        { STATE_BLEND,                                        state_blend_object  }, WINED3D_GL_EXT_NONE             },
     { STATE_STREAMSRC,                                    { STATE_STREAMSRC,                                    streamsrc           }, WINED3D_GL_EXT_NONE             },
     { STATE_VDECL,                                        { STATE_VDECL,                                        vdecl_miscpart      }, WINED3D_GL_EXT_NONE             },
-    { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface_cc        }, ARB_CLIP_CONTROL                },
-    { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface           }, WINED3D_GL_EXT_NONE             },
+    { STATE_RASTERIZER,                                   { STATE_RASTERIZER,                                   rasterizer_cc       }, ARB_CLIP_CONTROL                },
+    { STATE_RASTERIZER,                                   { STATE_RASTERIZER,                                   rasterizer          }, WINED3D_GL_EXT_NONE             },
     { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, WINED3D_GL_EXT_NONE             },
     { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       state_nop           }, ARB_CLIP_CONTROL                },
     { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin            }, WINED3D_GL_VERSION_2_0          },
     { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, WINED3D_GL_EXT_NONE             },
     { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       state_nop           }, ARB_CLIP_CONTROL                },
     { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin            }, WINED3D_GL_VERSION_2_0          },
@@ -5223,7 +4630,7 @@ const struct StateEntryTemplate misc_state_template[] =
     { STATE_RENDER(WINED3D_RS_STENCILFUNC),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILREF),                { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILMASK),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILFUNC),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILREF),                { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILMASK),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE            },
+    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite2s_ext}, EXT_STENCIL_TWO_SIDE        },
     { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite  }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE),       { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite  }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE),       { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
@@ -5290,8 +4697,6 @@ const struct StateEntryTemplate misc_state_template[] =
     { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 state_depthbias     }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_DEPTHBIASCLAMP),            { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  state_zvisible      }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 state_depthbias     }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_DEPTHBIASCLAMP),            { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  state_zvisible      }, WINED3D_GL_EXT_NONE             },
-    { STATE_RENDER(WINED3D_RS_DEPTHCLIP),                 { STATE_RENDER(WINED3D_RS_DEPTHCLIP),                 state_depthclip     }, ARB_DEPTH_CLAMP                 },
-    { STATE_RENDER(WINED3D_RS_DEPTHCLIP),                 { STATE_RENDER(WINED3D_RS_DEPTHCLIP),                 state_depthclip_w   }, WINED3D_GL_EXT_NONE             },
     /* Samplers */
     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, WINED3D_GL_EXT_NONE             },
     /* Samplers */
     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, WINED3D_GL_EXT_NONE             },
     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, WINED3D_GL_EXT_NONE             },
@@ -5650,7 +5055,6 @@ static const struct StateEntryTemplate vp_ffp_states[] =
     { STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend   }, ARB_VERTEX_BLEND                },
     { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend_w }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_POINTSIZE),                 { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
     { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend_w }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_POINTSIZE),                 { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
@@ -5823,7 +5227,7 @@ static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3
     caps->xyzrhw = FALSE;
     caps->ffp_generic_attributes = FALSE;
     caps->max_active_lights = gl_info->limits.lights;
     caps->xyzrhw = FALSE;
     caps->ffp_generic_attributes = FALSE;
     caps->max_active_lights = gl_info->limits.lights;
-    caps->max_vertex_blend_matrices = gl_info->limits.blends;
+    caps->max_vertex_blend_matrices = 1;
     caps->max_vertex_blend_matrix_index = 0;
     caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS
             | WINED3DVTXPCAPS_MATERIALSOURCE7
     caps->max_vertex_blend_matrix_index = 0;
     caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS
             | WINED3DVTXPCAPS_MATERIALSOURCE7
@@ -6081,7 +5485,7 @@ static void validate_state_table(struct StateEntry *state_table)
         STATE_VIEWPORT,
         STATE_LIGHT_TYPE,
         STATE_SCISSORRECT,
         STATE_VIEWPORT,
         STATE_LIGHT_TYPE,
         STATE_SCISSORRECT,
-        STATE_FRONTFACE,
+        STATE_RASTERIZER,
         STATE_POINTSPRITECOORDORIGIN,
         STATE_BASEVERTEXINDEX,
         STATE_FRAMEBUFFER,
         STATE_POINTSPRITECOORDORIGIN,
         STATE_BASEVERTEXINDEX,
         STATE_FRAMEBUFFER,
index c9b3527..397ddaa 100644 (file)
@@ -94,7 +94,6 @@ static const DWORD pixel_states_render[] =
     WINED3D_RS_ZENABLE,
     WINED3D_RS_ZFUNC,
     WINED3D_RS_ZWRITEENABLE,
     WINED3D_RS_ZENABLE,
     WINED3D_RS_ZFUNC,
     WINED3D_RS_ZWRITEENABLE,
-    WINED3D_RS_DEPTHCLIP,
 };
 
 static const DWORD pixel_states_texture[] =
 };
 
 static const DWORD pixel_states_texture[] =
@@ -815,20 +814,33 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
         stateblock->state.material = src_state->material;
     }
 
         stateblock->state.material = src_state->material;
     }
 
+    assert(src_state->viewport_count <= 1);
+
     if (stateblock->changed.viewport
     if (stateblock->changed.viewport
-            && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport)))
+            && (src_state->viewport_count != stateblock->state.viewport_count
+            || memcmp(src_state->viewports, stateblock->state.viewports,
+            src_state->viewport_count * sizeof(*stateblock->state.viewports))))
     {
     {
-        TRACE("Updating viewport.\n");
+        TRACE("Updating viewports.\n");
 
 
-        stateblock->state.viewport = src_state->viewport;
+        if ((stateblock->state.viewport_count = src_state->viewport_count))
+            memcpy(stateblock->state.viewports, src_state->viewports, sizeof(src_state->viewports));
+        else
+            memset(stateblock->state.viewports, 0, sizeof(*stateblock->state.viewports));
     }
 
     }
 
-    if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect,
-            &stateblock->state.scissor_rect, sizeof(stateblock->state.scissor_rect)))
+    if (stateblock->changed.scissorRect
+            && (src_state->scissor_rect_count != stateblock->state.scissor_rect_count
+            || memcmp(src_state->scissor_rects, stateblock->state.scissor_rects,
+                       src_state->scissor_rect_count * sizeof(*stateblock->state.scissor_rects))))
     {
     {
-        TRACE("Updating scissor rect.\n");
+        TRACE("Updating scissor rects.\n");
 
 
-        stateblock->state.scissor_rect = src_state->scissor_rect;
+        if ((stateblock->state.scissor_rect_count = src_state->scissor_rect_count))
+            memcpy(stateblock->state.scissor_rects, src_state->scissor_rects,
+                    src_state->scissor_rect_count * sizeof(*src_state->scissor_rects));
+        else
+            SetRectEmpty(stateblock->state.scissor_rects);
     }
 
     map = stateblock->changed.streamSource;
     }
 
     map = stateblock->changed.streamSource;
@@ -1060,10 +1072,11 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
         wined3d_device_set_material(device, &stateblock->state.material);
 
     if (stateblock->changed.viewport)
         wined3d_device_set_material(device, &stateblock->state.material);
 
     if (stateblock->changed.viewport)
-        wined3d_device_set_viewport(device, &stateblock->state.viewport);
+        wined3d_device_set_viewports(device, stateblock->state.viewport_count, stateblock->state.viewports);
 
     if (stateblock->changed.scissorRect)
 
     if (stateblock->changed.scissorRect)
-        wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect);
+        wined3d_device_set_scissor_rects(device, stateblock->state.scissor_rect_count,
+                stateblock->state.scissor_rects);
 
     map = stateblock->changed.streamSource;
     for (i = 0; map; map >>= 1, ++i)
 
     map = stateblock->changed.streamSource;
     for (i = 0; map; map >>= 1, ++i)
@@ -1246,7 +1259,6 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d
     state->render_states[WINED3D_RS_DEPTHBIAS] = 0;
     tmpfloat.f = 0.0f;
     state->render_states[WINED3D_RS_DEPTHBIASCLAMP] = tmpfloat.d;
     state->render_states[WINED3D_RS_DEPTHBIAS] = 0;
     tmpfloat.f = 0.0f;
     state->render_states[WINED3D_RS_DEPTHBIASCLAMP] = tmpfloat.d;
-    state->render_states[WINED3D_RS_DEPTHCLIP] = TRUE;
     state->render_states[WINED3D_RS_WRAP8] = 0;
     state->render_states[WINED3D_RS_WRAP9] = 0;
     state->render_states[WINED3D_RS_WRAP10] = 0;
     state->render_states[WINED3D_RS_WRAP8] = 0;
     state->render_states[WINED3D_RS_WRAP9] = 0;
     state->render_states[WINED3D_RS_WRAP10] = 0;
index ae32235..baad32e 100644 (file)
@@ -36,208 +36,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM
         | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER;
 
 static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM
         | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER;
 
-struct blt_info
-{
-    GLenum binding;
-    GLenum bind_target;
-    enum wined3d_gl_resource_type tex_type;
-    struct wined3d_vec3 texcoords[4];
-};
-
-struct float_rect
-{
-    float l;
-    float t;
-    float r;
-    float b;
-};
-
-static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float_rect *f)
-{
-    f->l = ((r->left * 2.0f) / w) - 1.0f;
-    f->t = ((r->top * 2.0f) / h) - 1.0f;
-    f->r = ((r->right * 2.0f) / w) - 1.0f;
-    f->b = ((r->bottom * 2.0f) / h) - 1.0f;
-}
-
-static void texture2d_get_blt_info(const struct wined3d_texture *texture,
-        unsigned int sub_resource_idx, const RECT *rect, struct blt_info *info)
-{
-    struct wined3d_vec3 *coords = info->texcoords;
-    struct float_rect f;
-    unsigned int level;
-    GLenum target;
-    GLsizei w, h;
-
-    level = sub_resource_idx % texture->level_count;
-    w = wined3d_texture_get_level_pow2_width(texture, level);
-    h = wined3d_texture_get_level_pow2_height(texture, level);
-    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
-
-    switch (target)
-    {
-        default:
-            FIXME("Unsupported texture target %#x.\n", target);
-            /* Fall back to GL_TEXTURE_2D */
-        case GL_TEXTURE_2D:
-            info->binding = GL_TEXTURE_BINDING_2D;
-            info->bind_target = GL_TEXTURE_2D;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_2D;
-            coords[0].x = (float)rect->left / w;
-            coords[0].y = (float)rect->top / h;
-            coords[0].z = 0.0f;
-
-            coords[1].x = (float)rect->right / w;
-            coords[1].y = (float)rect->top / h;
-            coords[1].z = 0.0f;
-
-            coords[2].x = (float)rect->left / w;
-            coords[2].y = (float)rect->bottom / h;
-            coords[2].z = 0.0f;
-
-            coords[3].x = (float)rect->right / w;
-            coords[3].y = (float)rect->bottom / h;
-            coords[3].z = 0.0f;
-            break;
-
-        case GL_TEXTURE_RECTANGLE_ARB:
-            info->binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
-            info->bind_target = GL_TEXTURE_RECTANGLE_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_RECT;
-            coords[0].x = rect->left;  coords[0].y = rect->top;    coords[0].z = 0.0f;
-            coords[1].x = rect->right; coords[1].y = rect->top;    coords[1].z = 0.0f;
-            coords[2].x = rect->left;  coords[2].y = rect->bottom; coords[2].z = 0.0f;
-            coords[3].x = rect->right; coords[3].y = rect->bottom; coords[3].z = 0.0f;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x =  1.0f;   coords[0].y = -f.t;   coords[0].z = -f.l;
-            coords[1].x =  1.0f;   coords[1].y = -f.t;   coords[1].z = -f.r;
-            coords[2].x =  1.0f;   coords[2].y = -f.b;   coords[2].z = -f.l;
-            coords[3].x =  1.0f;   coords[3].y = -f.b;   coords[3].z = -f.r;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x = -1.0f;   coords[0].y = -f.t;   coords[0].z = f.l;
-            coords[1].x = -1.0f;   coords[1].y = -f.t;   coords[1].z = f.r;
-            coords[2].x = -1.0f;   coords[2].y = -f.b;   coords[2].z = f.l;
-            coords[3].x = -1.0f;   coords[3].y = -f.b;   coords[3].z = f.r;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x = f.l;   coords[0].y =  1.0f;   coords[0].z = f.t;
-            coords[1].x = f.r;   coords[1].y =  1.0f;   coords[1].z = f.t;
-            coords[2].x = f.l;   coords[2].y =  1.0f;   coords[2].z = f.b;
-            coords[3].x = f.r;   coords[3].y =  1.0f;   coords[3].z = f.b;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x = f.l;   coords[0].y = -1.0f;   coords[0].z = -f.t;
-            coords[1].x = f.r;   coords[1].y = -1.0f;   coords[1].z = -f.t;
-            coords[2].x = f.l;   coords[2].y = -1.0f;   coords[2].z = -f.b;
-            coords[3].x = f.r;   coords[3].y = -1.0f;   coords[3].z = -f.b;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x = f.l;   coords[0].y = -f.t;   coords[0].z =  1.0f;
-            coords[1].x = f.r;   coords[1].y = -f.t;   coords[1].z =  1.0f;
-            coords[2].x = f.l;   coords[2].y = -f.b;   coords[2].z =  1.0f;
-            coords[3].x = f.r;   coords[3].y = -f.b;   coords[3].z =  1.0f;
-            break;
-
-        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
-            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
-            info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
-            cube_coords_float(rect, w, h, &f);
-
-            coords[0].x = -f.l;   coords[0].y = -f.t;   coords[0].z = -1.0f;
-            coords[1].x = -f.r;   coords[1].y = -f.t;   coords[1].z = -1.0f;
-            coords[2].x = -f.l;   coords[2].y = -f.b;   coords[2].z = -1.0f;
-            coords[3].x = -f.r;   coords[3].y = -f.b;   coords[3].z = -1.0f;
-            break;
-    }
-}
-
-/* Context activation is done by the caller. */
-void draw_textured_quad(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        struct wined3d_context *context, 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 blt_info info;
-
-    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)");
-
-    context_bind_texture(context, info.bind_target, texture->texture_rgb.name);
-
-    /* Filtering for StretchRect */
-    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAG_FILTER, wined3d_gl_mag_filter(filter));
-    checkGLcall("glTexParameteri");
-    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MIN_FILTER,
-            wined3d_gl_min_mip_filter(filter, WINED3D_TEXF_NONE));
-    checkGLcall("glTexParameteri");
-    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
-        gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
-    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();
-
-    /* Unbind the texture */
-    context_bind_texture(context, info.bind_target, 0);
-
-    /* We changed the filtering settings on the texture. Inform the
-     * container about this to get the filters reset properly next draw. */
-    texture->texture_rgb.sampler_desc.mag_filter = WINED3D_TEXF_POINT;
-    texture->texture_rgb.sampler_desc.min_filter = WINED3D_TEXF_POINT;
-    texture->texture_rgb.sampler_desc.mip_filter = WINED3D_TEXF_NONE;
-    texture->texture_rgb.sampler_desc.srgb_decode = FALSE;
-}
-
 /* Works correctly only for <= 4 bpp formats. */
 static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
 {
 /* Works correctly only for <= 4 bpp formats. */
 static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
 {
@@ -259,24 +57,19 @@ static BOOL texture2d_is_full_rect(const struct wined3d_texture *texture, unsign
     return TRUE;
 }
 
     return TRUE;
 }
 
-static void surface_depth_blt_fbo(const struct wined3d_device *device,
-        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
-        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect)
+static void texture2d_depth_blt_fbo(const struct wined3d_device *device, 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)
 {
 {
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    struct wined3d_texture *src_texture = src_surface->container;
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     DWORD src_mask, dst_mask;
     GLbitfield gl_mask;
 
     DWORD src_mask, dst_mask;
     GLbitfield gl_mask;
 
-    TRACE("device %p\n", device);
-    TRACE("src_surface %p, src_location %s, src_rect %s,\n",
-            src_surface, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect));
-    TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
-            dst_surface, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect));
+    TRACE("device %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.\n", device,
+            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));
 
     src_mask = src_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
     dst_mask = dst_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
 
     src_mask = src_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
     dst_mask = dst_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
@@ -302,14 +95,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     if (src_mask & WINED3DFMT_FLAG_STENCIL)
         gl_mask |= GL_STENCIL_BUFFER_BIT;
 
     if (src_mask & WINED3DFMT_FLAG_STENCIL)
         gl_mask |= GL_STENCIL_BUFFER_BIT;
 
-    context = context_acquire(device, NULL, 0);
-    if (!context->valid)
-    {
-        context_release(context);
-        WARN("Invalid context, skipping blit.\n");
-        return;
-    }
-
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. */
     wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, src_location);
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. */
     wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, src_location);
@@ -318,12 +103,12 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     else
         wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, dst_location);
 
     else
         wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, dst_location);
 
-    gl_info = context->gl_info;
-
-    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location);
+    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, 0,
+            &src_texture->resource, src_sub_resource_idx, src_location);
     context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
 
     context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
 
-    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, dst_surface, dst_location);
+    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, 0,
+            &dst_texture->resource, dst_sub_resource_idx, dst_location);
     context_set_draw_buffer(context, GL_NONE);
     context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
     context_set_draw_buffer(context, GL_NONE);
     context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -350,11 +135,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device,
     gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
             dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST);
     checkGLcall("glBlitFramebuffer()");
     gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
             dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST);
     checkGLcall("glBlitFramebuffer()");
-
-    if (wined3d_settings.strict_draw_ordering)
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
-
-    context_release(context);
 }
 
 static BOOL is_multisample_location(const struct wined3d_texture *texture, DWORD location)
 }
 
 static BOOL is_multisample_location(const struct wined3d_texture *texture, DWORD location)
@@ -368,31 +148,25 @@ static BOOL is_multisample_location(const struct wined3d_texture *texture, DWORD
 
 /* Blit between surface locations. Onscreen on different swapchains is not supported.
  * Depth / stencil is not supported. Context activation is done by the caller. */
 
 /* Blit between surface locations. Onscreen on different swapchains is not supported.
  * Depth / stencil is not supported. Context activation is done by the caller. */
-static void surface_blt_fbo(const struct wined3d_device *device,
-        struct wined3d_context *old_ctx, enum wined3d_texture_filter_type filter,
-        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in,
-        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
-{
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    struct wined3d_texture *src_texture = src_surface->container;
+static void texture2d_blt_fbo(const struct wined3d_device *device, struct wined3d_context *context,
+        enum wined3d_texture_filter_type filter, 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)
+{
+    struct wined3d_texture *required_texture, *restore_texture;
+    unsigned int required_idx, restore_idx;
     const struct wined3d_gl_info *gl_info;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context = old_ctx;
-    struct wined3d_surface *required_rt, *restore_rt = NULL;
-    RECT src_rect, dst_rect;
     GLenum gl_filter;
     GLenum buffer;
     GLenum gl_filter;
     GLenum buffer;
+    RECT s, d;
     int i;
 
     int i;
 
-    TRACE("device %p, filter %s,\n", device, debug_d3dtexturefiltertype(filter));
-    TRACE("src_surface %p, src_location %s, src_rect %s,\n",
-            src_surface, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect_in));
-    TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
-            dst_surface, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect_in));
-
-    src_rect = *src_rect_in;
-    dst_rect = *dst_rect_in;
+    TRACE("device %p, context %p, filter %s, 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.\n",
+            device, context, debug_d3dtexturefiltertype(filter), 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));
 
     switch (filter)
     {
 
     switch (filter)
     {
@@ -411,31 +185,43 @@ static void surface_blt_fbo(const struct wined3d_device *device,
     /* Resolve the source surface first if needed. */
     if (is_multisample_location(src_texture, src_location)
             && (src_texture->resource.format->id != dst_texture->resource.format->id
     /* Resolve the source surface first if needed. */
     if (is_multisample_location(src_texture, src_location)
             && (src_texture->resource.format->id != dst_texture->resource.format->id
-                || abs(src_rect.bottom - src_rect.top) != abs(dst_rect.bottom - dst_rect.top)
-                || abs(src_rect.right - src_rect.left) != abs(dst_rect.right - dst_rect.left)))
+                || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top)
+                || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left)))
         src_location = WINED3D_LOCATION_RB_RESOLVED;
 
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. (And is
      * in fact harmful if we're being called by surface_load_location() with
      * the purpose of loading the destination surface.) */
         src_location = WINED3D_LOCATION_RB_RESOLVED;
 
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. (And is
      * in fact harmful if we're being called by surface_load_location() with
      * the purpose of loading the destination surface.) */
-    wined3d_texture_load_location(src_texture, src_sub_resource_idx, old_ctx, src_location);
-    if (!texture2d_is_full_rect(dst_texture, dst_sub_resource_idx % dst_texture->level_count, &dst_rect))
-        wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, old_ctx, dst_location);
+    wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, src_location);
+    if (!texture2d_is_full_rect(dst_texture, dst_sub_resource_idx % dst_texture->level_count, dst_rect))
+        wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, dst_location);
     else
     else
-        wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, old_ctx, dst_location);
+        wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, dst_location);
 
 
 
 
-    if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface;
-    else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface;
-    else required_rt = NULL;
+    if (src_location == WINED3D_LOCATION_DRAWABLE)
+    {
+        required_texture = src_texture;
+        required_idx = src_sub_resource_idx;
+    }
+    else if (dst_location == WINED3D_LOCATION_DRAWABLE)
+    {
+        required_texture = dst_texture;
+        required_idx = dst_sub_resource_idx;
+    }
+    else
+    {
+        required_texture = NULL;
+        required_idx = 0;
+    }
 
 
-    restore_rt = context_get_rt_surface(old_ctx);
-    if (restore_rt != required_rt)
-        context = context_acquire(device, required_rt ? required_rt->container : NULL,
-                required_rt ? surface_get_sub_resource_idx(required_rt) : 0);
+    restore_texture = context->current_rt.texture;
+    restore_idx = context->current_rt.sub_resource_idx;
+    if (restore_texture != required_texture || restore_idx != required_idx)
+        context = context_acquire(device, required_texture, required_idx);
     else
     else
-        restore_rt = NULL;
+        restore_texture = NULL;
 
     if (!context->valid)
     {
 
     if (!context->valid)
     {
@@ -448,34 +234,40 @@ static void surface_blt_fbo(const struct wined3d_device *device,
 
     if (src_location == WINED3D_LOCATION_DRAWABLE)
     {
 
     if (src_location == WINED3D_LOCATION_DRAWABLE)
     {
-        TRACE("Source surface %p is onscreen.\n", src_surface);
+        TRACE("Source texture %p is onscreen.\n", src_texture);
         buffer = wined3d_texture_get_gl_buffer(src_texture);
         buffer = wined3d_texture_get_gl_buffer(src_texture);
-        surface_translate_drawable_coords(src_surface, context->win_handle, &src_rect);
+        s = *src_rect;
+        wined3d_texture_translate_drawable_coords(src_texture, context->win_handle, &s);
+        src_rect = &s;
     }
     else
     {
     }
     else
     {
-        TRACE("Source surface %p is offscreen.\n", src_surface);
+        TRACE("Source texture %p is offscreen.\n", src_texture);
         buffer = GL_COLOR_ATTACHMENT0;
     }
 
         buffer = GL_COLOR_ATTACHMENT0;
     }
 
-    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location);
+    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER,
+            &src_texture->resource, src_sub_resource_idx, NULL, 0, src_location);
     gl_info->gl_ops.gl.p_glReadBuffer(buffer);
     checkGLcall("glReadBuffer()");
     context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
 
     if (dst_location == WINED3D_LOCATION_DRAWABLE)
     {
     gl_info->gl_ops.gl.p_glReadBuffer(buffer);
     checkGLcall("glReadBuffer()");
     context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
 
     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);
         buffer = wined3d_texture_get_gl_buffer(dst_texture);
-        surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
+        d = *dst_rect;
+        wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d);
+        dst_rect = &d;
     }
     else
     {
     }
     else
     {
-        TRACE("Destination surface %p is offscreen.\n", dst_surface);
+        TRACE("Destination texture %p is offscreen.\n", dst_texture);
         buffer = GL_COLOR_ATTACHMENT0;
     }
 
         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);
     context_set_draw_buffer(context, buffer);
     context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -487,16 +279,15 @@ static void surface_blt_fbo(const struct wined3d_device *device,
     gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
 
     gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
 
-    gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
-            dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter);
+    gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
+            dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, GL_COLOR_BUFFER_BIT, gl_filter);
     checkGLcall("glBlitFramebuffer()");
 
     checkGLcall("glBlitFramebuffer()");
 
-    if (wined3d_settings.strict_draw_ordering || (dst_location == WINED3D_LOCATION_DRAWABLE
-            && dst_texture->swapchain->front_buffer == dst_texture))
+    if (dst_location == WINED3D_LOCATION_DRAWABLE && dst_texture->swapchain->front_buffer == dst_texture)
         gl_info->gl_ops.gl.p_glFlush();
 
         gl_info->gl_ops.gl.p_glFlush();
 
-    if (restore_rt)
-        context_restore(context, restore_rt);
+    if (restore_texture)
+        context_restore(context, restore_texture, restore_idx);
 }
 
 static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_gl_info *gl_info,
 }
 
 static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_gl_info *gl_info,
@@ -513,6 +304,9 @@ static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct win
     if (!(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
         return FALSE;
 
     if (!(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
         return FALSE;
 
+    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
+        return FALSE;
+
     switch (blit_op)
     {
         case WINED3D_BLIT_OP_COLOR_BLIT:
     switch (blit_op)
     {
         case WINED3D_BLIT_OP_COLOR_BLIT:
@@ -550,12 +344,11 @@ static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct win
 /* This call just downloads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
 /* This call just downloads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
-static void surface_download_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
-        DWORD dst_location)
+static void texture2d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        const struct wined3d_context *context, DWORD dst_location)
 {
 {
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
     const struct wined3d_format *format = texture->resource.format;
     const struct wined3d_format *format = texture->resource.format;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_texture_sub_resource *sub_resource;
     unsigned int dst_row_pitch, dst_slice_pitch;
     unsigned int src_row_pitch, src_slice_pitch;
     struct wined3d_texture_sub_resource *sub_resource;
     unsigned int dst_row_pitch, dst_slice_pitch;
     unsigned int src_row_pitch, src_slice_pitch;
@@ -565,10 +358,11 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
     GLenum target;
     void *mem;
 
     GLenum target;
     void *mem;
 
-    /* Only support read back of converted P8 surfaces. */
+    /* Only support read back of converted P8 textures. */
     if (texture->flags & WINED3D_TEXTURE_CONVERTED && format->id != WINED3DFMT_P8_UINT && !format->download)
     {
     if (texture->flags & WINED3D_TEXTURE_CONVERTED && format->id != WINED3DFMT_P8_UINT && !format->download)
     {
-        ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id));
+        ERR("Trying to read back converted texture %p, %u with format %s.\n",
+                texture, sub_resource_idx, debug_d3dformat(format->id));
         return;
     }
 
         return;
     }
 
@@ -588,7 +382,7 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
         if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
             ERR("Array texture %p uses NP2 emulation.\n", texture);
 
         if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
             ERR("Array texture %p uses NP2 emulation.\n", texture);
 
-        WARN_(d3d_perf)("Downloading all miplevel layers to get the surface data for a single sub-resource.\n");
+        WARN_(d3d_perf)("Downloading all miplevel layers to get the data for a single sub-resource.\n");
 
         if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size)))
         {
 
         if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size)))
         {
@@ -631,7 +425,8 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
         if (data.buffer_object)
             ERR("Converted texture %p uses PBO unexpectedly.\n", texture);
 
         if (data.buffer_object)
             ERR("Converted texture %p uses PBO unexpectedly.\n", texture);
 
-        WARN_(d3d_perf)("Downloading converted surface %p with format %s.\n", surface, debug_d3dformat(format->id));
+        WARN_(d3d_perf)("Downloading converted texture %p, %u with format %s.\n",
+                texture, sub_resource_idx, debug_d3dformat(format->id));
 
         f = *format;
         f.byte_count = format->conv_byte_count;
 
         f = *format;
         f.byte_count = format->conv_byte_count;
@@ -665,16 +460,16 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
 
     if (texture->resource.format_flags & WINED3DFMT_FLAG_COMPRESSED)
     {
 
     if (texture->resource.format_flags & WINED3DFMT_FLAG_COMPRESSED)
     {
-        TRACE("Downloading compressed surface %p, level %u, format %#x, type %#x, data %p.\n",
-                surface, level, format->glFormat, format->glType, mem);
+        TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
+                texture, sub_resource_idx, level, format->glFormat, format->glType, mem);
 
         GL_EXTCALL(glGetCompressedTexImage(target, level, mem));
         checkGLcall("glGetCompressedTexImage");
     }
     else
     {
 
         GL_EXTCALL(glGetCompressedTexImage(target, level, mem));
         checkGLcall("glGetCompressedTexImage");
     }
     else
     {
-        TRACE("Downloading surface %p, level %u, format %#x, type %#x, data %p.\n",
-                surface, level, format->glFormat, format->glType, mem);
+        TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
+                texture, sub_resource_idx, level, format->glFormat, format->glType, mem);
 
         gl_info->gl_ops.gl.p_glGetTexImage(target, level, format->glFormat, format->glType, mem);
         checkGLcall("glGetTexImage");
 
         gl_info->gl_ops.gl.p_glGetTexImage(target, level, format->glFormat, format->glType, mem);
         checkGLcall("glGetTexImage");
@@ -773,291 +568,6 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
     heap_free(temporary_mem);
 }
 
     heap_free(temporary_mem);
 }
 
-/* This call just uploads data, the caller is responsible for binding the
- * correct texture. */
-/* Context activation is done by the caller. */
-void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
-        const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
-        BOOL srgb, const struct wined3d_const_bo_address *data)
-{
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
-    UINT update_w = src_rect->right - src_rect->left;
-    UINT update_h = src_rect->bottom - src_rect->top;
-    unsigned int level, layer;
-    GLenum target;
-
-    TRACE("surface %p, gl_info %p, format %s, src_rect %s, src_pitch %u, dst_point %s, srgb %#x, data {%#x:%p}.\n",
-            surface, gl_info, debug_d3dformat(format->id), wine_dbgstr_rect(src_rect), src_pitch,
-            wine_dbgstr_point(dst_point), srgb, data->buffer_object, data->addr);
-
-    if (texture->sub_resources[sub_resource_idx].map_count)
-    {
-        WARN("Uploading a surface that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n");
-        texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM;
-    }
-
-    if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_HEIGHT_SCALE)
-    {
-        update_h *= format->height_scale.numerator;
-        update_h /= format->height_scale.denominator;
-    }
-
-    if (data->buffer_object)
-    {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object));
-        checkGLcall("glBindBuffer");
-    }
-
-    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
-    level = sub_resource_idx % texture->level_count;
-    layer = sub_resource_idx / texture->level_count;
-
-    if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
-    {
-        unsigned int dst_row_pitch, dst_slice_pitch;
-        const BYTE *addr = data->addr;
-        GLenum internal;
-
-        addr += (src_rect->top / format->block_height) * src_pitch;
-        addr += (src_rect->left / format->block_width) * format->block_byte_count;
-
-        if (srgb)
-            internal = format->glGammaInternal;
-        else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
-                && wined3d_resource_is_offscreen(&texture->resource))
-            internal = format->rtInternal;
-        else
-            internal = format->glInternal;
-
-        wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch);
-
-        TRACE("Uploading compressed data, target %#x, level %u, layer %u, x %d, y %d, w %u, h %u, "
-                "format %#x, image_size %#x, addr %p.\n",
-                target, level, layer, dst_point->x, dst_point->y,
-                update_w, update_h, internal, dst_slice_pitch, addr);
-
-        if (dst_row_pitch == src_pitch)
-        {
-            if (target == GL_TEXTURE_2D_ARRAY)
-            {
-                GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_point->x, dst_point->y,
-                        layer, update_w, update_h, 1, internal, dst_slice_pitch, addr));
-            }
-            else
-            {
-                GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_point->x, dst_point->y,
-                        update_w, update_h, internal, dst_slice_pitch, addr));
-            }
-        }
-        else
-        {
-            UINT row_count = (update_h + format->block_height - 1) / format->block_height;
-            UINT row, y;
-
-            /* glCompressedTexSubImage2D() ignores pixel store state, so we
-             * can't use the unpack row length like for glTexSubImage2D. */
-            for (row = 0, y = dst_point->y; row < row_count; ++row)
-            {
-                if (target == GL_TEXTURE_2D_ARRAY)
-                {
-                    GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_point->x, y,
-                            layer, update_w, format->block_height, 1, internal, dst_row_pitch, addr));
-                }
-                else
-                {
-                    GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_point->x, y,
-                            update_w, format->block_height, internal, dst_row_pitch, addr));
-                }
-
-                y += format->block_height;
-                addr += src_pitch;
-            }
-        }
-        checkGLcall("Upload compressed surface data");
-    }
-    else
-    {
-        const BYTE *addr = data->addr;
-
-        addr += src_rect->top * src_pitch;
-        addr += src_rect->left * format->byte_count;
-
-        TRACE("Uploading data, target %#x, level %u, layer %u, x %d, y %d, w %u, h %u, "
-                "format %#x, type %#x, addr %p.\n",
-                target, level, layer, dst_point->x, dst_point->y,
-                update_w, update_h, format->glFormat, format->glType, addr);
-
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_pitch / format->byte_count);
-        if (target == GL_TEXTURE_2D_ARRAY)
-        {
-            GL_EXTCALL(glTexSubImage3D(target, level, dst_point->x, dst_point->y,
-                    layer, update_w, update_h, 1, format->glFormat, format->glType, addr));
-        }
-        else
-        {
-            gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_point->x, dst_point->y,
-                    update_w, update_h, format->glFormat, format->glType, addr);
-        }
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-        checkGLcall("Upload surface data");
-    }
-
-    if (data->buffer_object)
-    {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
-        checkGLcall("glBindBuffer");
-    }
-
-    if (wined3d_settings.strict_draw_ordering)
-        gl_info->gl_ops.gl.p_glFlush();
-
-    if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE)
-    {
-        struct wined3d_device *device = texture->resource.device;
-        unsigned int i;
-
-        for (i = 0; i < device->context_count; ++i)
-        {
-            context_surface_update(device->contexts[i], surface);
-        }
-    }
-}
-
-static HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point,
-        struct wined3d_surface *src_surface, const RECT *src_rect)
-{
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
-    struct wined3d_texture *src_texture = src_surface->container;
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    unsigned int src_row_pitch, src_slice_pitch;
-    const struct wined3d_gl_info *gl_info;
-    unsigned int src_level, dst_level;
-    struct wined3d_context *context;
-    struct wined3d_bo_address data;
-    UINT update_w, update_h;
-
-    TRACE("dst_surface %p, dst_point %s, src_surface %p, src_rect %s.\n",
-            dst_surface, wine_dbgstr_point(dst_point),
-            src_surface, wine_dbgstr_rect(src_rect));
-
-    context = context_acquire(dst_texture->resource.device, NULL, 0);
-    gl_info = context->gl_info;
-
-    /* Only load the surface for partial updates. For newly allocated texture
-     * the texture wouldn't be the current location, and we'd upload zeroes
-     * just to overwrite them again. */
-    update_w = src_rect->right - src_rect->left;
-    update_h = src_rect->bottom - src_rect->top;
-    dst_level = dst_sub_resource_idx % dst_texture->level_count;
-    if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
-            && update_h == wined3d_texture_get_level_height(dst_texture, dst_level))
-        wined3d_texture_prepare_texture(dst_texture, context, FALSE);
-    else
-        wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
-    wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
-
-    src_level = src_sub_resource_idx % src_texture->level_count;
-    wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
-            src_texture->sub_resources[src_sub_resource_idx].locations);
-    wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
-
-    wined3d_surface_upload_data(dst_surface, gl_info, src_texture->resource.format, src_rect,
-            src_row_pitch, dst_point, FALSE, wined3d_const_bo_address(&data));
-
-    context_release(context);
-
-    wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
-    wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
-
-    return WINED3D_OK;
-}
-
-/* In D3D the depth stencil dimensions have to be greater than or equal to the
- * render target dimensions. With FBOs, the dimensions have to be an exact match. */
-/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
-/* Context activation is done by the caller. */
-void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_rendertarget_info *rt)
-{
-    unsigned int sub_resource_idx, width, height, level;
-    struct wined3d_renderbuffer_entry *entry;
-    const struct wined3d_texture *texture;
-    const struct wined3d_gl_info *gl_info;
-    unsigned int src_width, src_height;
-    GLuint renderbuffer = 0;
-
-    texture = surface->container;
-    gl_info = &texture->resource.device->adapter->gl_info;
-    sub_resource_idx = surface_get_sub_resource_idx(surface);
-    level = sub_resource_idx % texture->level_count;
-
-    if (rt && rt->resource->format->id != WINED3DFMT_NULL)
-    {
-        struct wined3d_texture *rt_texture;
-        unsigned int rt_level;
-
-        if (rt->resource->type == WINED3D_RTYPE_BUFFER)
-        {
-            FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
-            return;
-        }
-        rt_texture = wined3d_texture_from_resource(rt->resource);
-        rt_level = rt->sub_resource_idx % rt_texture->level_count;
-
-        width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
-        height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
-    }
-    else
-    {
-        width = wined3d_texture_get_level_pow2_width(texture, level);
-        height = wined3d_texture_get_level_pow2_height(texture, level);
-    }
-
-    src_width = wined3d_texture_get_level_pow2_width(texture, level);
-    src_height = wined3d_texture_get_level_pow2_height(texture, level);
-
-    /* A depth stencil smaller than the render target is not valid */
-    if (width > src_width || height > src_height) return;
-
-    /* Remove any renderbuffer set if the sizes match */
-    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
-            || (width == src_width && height == src_height))
-    {
-        surface->current_renderbuffer = NULL;
-        return;
-    }
-
-    /* Look if we've already got a renderbuffer of the correct dimensions */
-    LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-    {
-        if (entry->width == width && entry->height == height)
-        {
-            renderbuffer = entry->id;
-            surface->current_renderbuffer = entry;
-            break;
-        }
-    }
-
-    if (!renderbuffer)
-    {
-        gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
-        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
-        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
-                texture->resource.format->glInternal, width, height);
-
-        entry = heap_alloc(sizeof(*entry));
-        entry->width = width;
-        entry->height = height;
-        entry->id = renderbuffer;
-        list_add_head(&surface->renderbuffers, &entry->entry);
-
-        surface->current_renderbuffer = entry;
-    }
-
-    checkGLcall("set_compatible_renderbuffer");
-}
-
 /* See also float_16_to_32() in wined3d_private.h */
 static inline unsigned short float_32_to_16(const float *in)
 {
 /* See also float_16_to_32() in wined3d_private.h */
 static inline unsigned short float_32_to_16(const float *in)
 {
@@ -1480,7 +990,6 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
     const struct wined3d_format *src_format = src_texture->resource.format;
     struct wined3d_device *device = src_texture->resource.device;
     const struct d3dfmt_converter_desc *conv = NULL;
     const struct wined3d_format *src_format = src_texture->resource.format;
     struct wined3d_device *device = src_texture->resource.device;
     const struct d3dfmt_converter_desc *conv = NULL;
-    const struct wined3d_gl_info *gl_info = NULL;
     unsigned int src_row_pitch, src_slice_pitch;
     struct wined3d_context *context = NULL;
     struct wined3d_texture *dst_texture;
     unsigned int src_row_pitch, src_slice_pitch;
     struct wined3d_context *context = NULL;
     struct wined3d_texture *dst_texture;
@@ -1518,10 +1027,7 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
     }
 
     if (device->d3d_initialized)
     }
 
     if (device->d3d_initialized)
-    {
         context = context_acquire(device, NULL, 0);
         context = context_acquire(device, NULL, 0);
-        gl_info = context->gl_info;
-    }
 
     map_binding = src_texture->resource.map_binding;
     if (!wined3d_texture_load_location(src_texture, sub_resource_idx, context, map_binding))
 
     map_binding = src_texture->resource.map_binding;
     if (!wined3d_texture_load_location(src_texture, sub_resource_idx, context, map_binding))
@@ -1555,15 +1061,14 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
     }
     else
     {
     }
     else
     {
-        RECT src_rect = {0, 0, desc.width, desc.height};
-        POINT dst_point = {0, 0};
+        struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
 
         TRACE("Using upload conversion.\n");
 
         wined3d_texture_prepare_texture(dst_texture, context, FALSE);
         wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
 
         TRACE("Using upload conversion.\n");
 
         wined3d_texture_prepare_texture(dst_texture, context, FALSE);
         wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
-        wined3d_surface_upload_data(dst_texture->sub_resources[0].u.surface, gl_info, src_format,
-                &src_rect, src_row_pitch, &dst_point, FALSE, wined3d_const_bo_address(&src_data));
+        wined3d_texture_upload_data(dst_texture, 0, context, src_format, &src_box,
+                wined3d_const_bo_address(&src_data), src_row_pitch, src_slice_pitch, 0, 0, 0, FALSE);
 
         wined3d_texture_validate_location(dst_texture, 0, WINED3D_LOCATION_TEXTURE_RGB);
         wined3d_texture_invalidate_location(dst_texture, 0, ~WINED3D_LOCATION_TEXTURE_RGB);
 
         wined3d_texture_validate_location(dst_texture, 0, WINED3D_LOCATION_TEXTURE_RGB);
         wined3d_texture_invalidate_location(dst_texture, 0, ~WINED3D_LOCATION_TEXTURE_RGB);
@@ -1575,18 +1080,16 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
     return dst_texture;
 }
 
     return dst_texture;
 }
 
-static void read_from_framebuffer(struct wined3d_surface *surface,
-        struct wined3d_context *old_ctx, DWORD src_location, DWORD dst_location)
+static void texture2d_read_from_framebuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD src_location, DWORD dst_location)
 {
 {
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_device *device = texture->resource.device;
-    struct wined3d_context *context = old_ctx;
-    struct wined3d_surface *restore_rt = NULL;
+    struct wined3d_texture *restore_texture;
     const struct wined3d_gl_info *gl_info;
     unsigned int row_pitch, slice_pitch;
     unsigned int width, height, level;
     struct wined3d_bo_address data;
     const struct wined3d_gl_info *gl_info;
     unsigned int row_pitch, slice_pitch;
     unsigned int width, height, level;
     struct wined3d_bo_address data;
+    unsigned int restore_idx;
     BYTE *row, *top, *bottom;
     BOOL src_is_upside_down;
     unsigned int i;
     BYTE *row, *top, *bottom;
     BOOL src_is_upside_down;
     unsigned int i;
@@ -1594,16 +1097,18 @@ static void read_from_framebuffer(struct wined3d_surface *surface,
 
     wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
 
 
     wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
 
-    restore_rt = context_get_rt_surface(old_ctx);
-    if (restore_rt != surface)
+    restore_texture = context->current_rt.texture;
+    restore_idx = context->current_rt.sub_resource_idx;
+    if (restore_texture != texture || restore_idx != sub_resource_idx)
         context = context_acquire(device, texture, sub_resource_idx);
     else
         context = context_acquire(device, texture, sub_resource_idx);
     else
-        restore_rt = NULL;
+        restore_texture = NULL;
     gl_info = context->gl_info;
 
     if (src_location != texture->resource.draw_binding)
     {
     gl_info = context->gl_info;
 
     if (src_location != texture->resource.draw_binding)
     {
-        context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL, src_location);
+        context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER,
+                &texture->resource, sub_resource_idx, NULL, 0, src_location);
         context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
         context_invalidate_state(context, STATE_FRAMEBUFFER);
     }
         context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
         context_invalidate_state(context, STATE_FRAMEBUFFER);
     }
@@ -1697,8 +1202,8 @@ error:
         checkGLcall("glBindBuffer");
     }
 
         checkGLcall("glBindBuffer");
     }
 
-    if (restore_rt)
-        context_restore(context, restore_rt);
+    if (restore_texture)
+        context_restore(context, restore_texture, restore_idx);
 }
 
 /* Read the framebuffer contents into a texture. Note that this function
 }
 
 /* Read the framebuffer contents into a texture. Note that this function
@@ -1707,22 +1212,21 @@ error:
  *
  * Context activation is done by the caller. This function may temporarily
  * switch to a different context and restore the original one before return. */
  *
  * Context activation is done by the caller. This function may temporarily
  * switch to a different context and restore the original one before return. */
-void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct wined3d_context *old_ctx)
+void texture2d_load_fb_texture(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, BOOL srgb, struct wined3d_context *context)
 {
 {
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_device *device = texture->resource.device;
+    struct wined3d_texture *restore_texture;
     const struct wined3d_gl_info *gl_info;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context = old_ctx;
-    struct wined3d_surface *restore_rt = NULL;
-    unsigned int level;
+    unsigned int restore_idx, level;
     GLenum target;
 
     GLenum target;
 
-    restore_rt = context_get_rt_surface(old_ctx);
-    if (restore_rt != surface)
+    restore_texture = context->current_rt.texture;
+    restore_idx = context->current_rt.sub_resource_idx;
+    if (restore_texture != texture || restore_idx != sub_resource_idx)
         context = context_acquire(device, texture, sub_resource_idx);
     else
         context = context_acquire(device, texture, sub_resource_idx);
     else
-        restore_rt = NULL;
+        restore_texture = NULL;
 
     gl_info = context->gl_info;
     device_invalidate_state(device, STATE_FRAMEBUFFER);
 
     gl_info = context->gl_info;
     device_invalidate_state(device, STATE_FRAMEBUFFER);
@@ -1730,7 +1234,7 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct
     wined3d_texture_prepare_texture(texture, context, srgb);
     wined3d_texture_bind_and_dirtify(texture, context, srgb);
 
     wined3d_texture_prepare_texture(texture, context, srgb);
     wined3d_texture_bind_and_dirtify(texture, context, srgb);
 
-    TRACE("Reading back offscreen render target %p.\n", surface);
+    TRACE("Reading back offscreen render target %p, %u.\n", texture, sub_resource_idx);
 
     if (wined3d_resource_is_offscreen(&texture->resource))
         gl_info->gl_ops.gl.p_glReadBuffer(context_get_offscreen_gl_buffer(context));
 
     if (wined3d_resource_is_offscreen(&texture->resource))
         gl_info->gl_ops.gl.p_glReadBuffer(context_get_offscreen_gl_buffer(context));
@@ -1745,19 +1249,16 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct
             wined3d_texture_get_level_height(texture, level));
     checkGLcall("glCopyTexSubImage2D");
 
             wined3d_texture_get_level_height(texture, level));
     checkGLcall("glCopyTexSubImage2D");
 
-    if (restore_rt)
-        context_restore(context, restore_rt);
+    if (restore_texture)
+        context_restore(context, restore_texture, restore_idx);
 }
 
 /* Does a direct frame buffer -> texture copy. Stretching is done with single
  * pixel copy calls. */
 }
 
 /* Does a direct frame buffer -> texture copy. Stretching is done with single
  * pixel copy calls. */
-static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface,
-        const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter)
+static void fb_copy_to_texture_direct(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        const RECT *dst_rect_in, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+        const RECT *src_rect, enum wined3d_texture_filter_type filter)
 {
 {
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_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;
     unsigned int src_height, src_level, dst_level;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_device *device = dst_texture->resource.device;
     unsigned int src_height, src_level, dst_level;
     const struct wined3d_gl_info *gl_info;
@@ -1871,14 +1372,11 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc
 }
 
 /* Uses the hardware to stretch and flip the image */
 }
 
 /* Uses the hardware to stretch and flip the image */
-static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface,
-        const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter)
+static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        const RECT *dst_rect_in, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+        const RECT *src_rect, enum wined3d_texture_filter_type filter)
 {
     unsigned int src_width, src_height, src_pow2_width, src_pow2_height, src_level;
 {
     unsigned int src_width, src_height, src_pow2_width, src_pow2_height, src_level;
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_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;
     GLenum src_target, dst_target, texture_target;
     GLuint src, backup = 0;
     struct wined3d_device *device = dst_texture->resource.device;
     GLenum src_target, dst_target, texture_target;
     GLuint src, backup = 0;
@@ -1900,7 +1398,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
     /* Activate the Proper context for reading from the source surface, set it up for blitting */
     context = context_acquire(device, src_texture, src_sub_resource_idx);
     gl_info = context->gl_info;
     /* Activate the Proper context for reading from the source surface, set it up for blitting */
     context = context_acquire(device, src_texture, src_sub_resource_idx);
     gl_info = context->gl_info;
-    context_apply_blit_state(context, device);
+    context_apply_ffp_blit_state(context, device);
     wined3d_texture_load(dst_texture, context, FALSE);
 
     offscreen_buffer = context_get_offscreen_gl_buffer(context);
     wined3d_texture_load(dst_texture, context, FALSE);
 
     offscreen_buffer = context_get_offscreen_gl_buffer(context);
@@ -1950,7 +1448,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
         checkGLcall("glEnable(texture_target)");
 
         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
         checkGLcall("glEnable(texture_target)");
 
         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
-        surface_get_sub_resource(src_surface)->locations &= ~WINED3D_LOCATION_TEXTURE_RGB;
+        src_texture->sub_resources[src_sub_resource_idx].locations &= ~WINED3D_LOCATION_TEXTURE_RGB;
     }
 
     /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
     }
 
     /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
@@ -2146,9 +1644,6 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
         checkGLcall("glDeleteTextures(1, &backup)");
     }
 
         checkGLcall("glDeleteTextures(1, &backup)");
     }
 
-    if (wined3d_settings.strict_draw_ordering)
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
-
     context_release(context);
 
     /* The texture is now most up to date - If the surface is a render target
     context_release(context);
 
     /* The texture is now most up to date - If the surface is a render target
@@ -2157,47 +1652,24 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
     wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
 }
 
     wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
 }
 
-/* Front buffer coordinates are always full screen coordinates, but our GL
- * drawable is limited to the window's client area. The sysmem and texture
- * copies do have the full screen size. Note that GL has a bottom-left
- * origin, while D3D has a top-left origin. */
-void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect)
+static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+        const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
 {
 {
-    struct wined3d_texture *texture = surface->container;
-    POINT offset = {0, 0};
-    UINT drawable_height;
-    RECT windowsize;
+    struct wined3d_swapchain *src_swapchain, *dst_swapchain;
+    const struct wined3d_rendertarget_view *rtv;
 
 
-    if (!texture->swapchain)
-        return;
+    TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, "
+            "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n",
+            dst_texture, dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), src_texture, src_sub_resource_idx,
+            wine_dbgstr_rect(src_rect), flags, fx, debug_d3dtexturefiltertype(filter));
 
 
-    if (texture == texture->swapchain->front_buffer)
+    if (dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D)
     {
     {
-        ScreenToClient(window, &offset);
-        OffsetRect(rect, offset.x, offset.y);
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_texture->resource.type));
+        return WINED3DERR_INVALIDCALL;
     }
 
     }
 
-    GetClientRect(window, &windowsize);
-    drawable_height = windowsize.bottom - windowsize.top;
-
-    rect->top = drawable_height - rect->top;
-    rect->bottom = drawable_height - rect->bottom;
-}
-
-static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RECT *dst_rect,
-        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
-        const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
-{
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    struct wined3d_device *device = dst_texture->resource.device;
-    const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]);
-    struct wined3d_swapchain *src_swapchain, *dst_swapchain;
-    struct wined3d_texture *src_texture;
-
-    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
-            dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect),
-            flags, fx, debug_d3dtexturefiltertype(filter));
-
     /* Get the swapchain. One of the surfaces has to be a primary surface. */
     if (!(dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
     {
     /* Get the swapchain. One of the surfaces has to be a primary surface. */
     if (!(dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
     {
@@ -2205,27 +1677,19 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
-    dst_swapchain = dst_texture->swapchain;
-
-    if (src_surface)
+    if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
     {
     {
-        src_texture = src_surface->container;
-        if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
-        {
-            WARN("Source resource is not GPU accessible, rejecting GL blit.\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-
-        src_swapchain = src_texture->swapchain;
-    }
-    else
-    {
-        src_texture = NULL;
-        src_swapchain = NULL;
+        WARN("Source resource is not GPU accessible, rejecting GL blit.\n");
+        return WINED3DERR_INVALIDCALL;
     }
 
     }
 
+    src_swapchain = src_texture->swapchain;
+    dst_swapchain = dst_texture->swapchain;
+
     /* Early sort out of cases where no render target is used */
     /* Early sort out of cases where no render target is used */
-    if (!dst_swapchain && !src_swapchain && src_surface != rt && dst_surface != rt)
+    if (!(rtv = dst_texture->resource.device->fb.render_targets[0]) || (!src_swapchain && !dst_swapchain
+            && (&src_texture->resource != rtv->resource || src_sub_resource_idx != rtv->sub_resource_idx)
+            && (&dst_texture->resource != rtv->resource || dst_sub_resource_idx != rtv->sub_resource_idx)))
     {
         TRACE("No surface is render target, not using hardware blit.\n");
         return WINED3DERR_INVALIDCALL;
     {
         TRACE("No surface is render target, not using hardware blit.\n");
         return WINED3DERR_INVALIDCALL;
@@ -2254,16 +1718,18 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
     if (dst_swapchain)
     {
         /* Handled with regular texture -> swapchain blit */
     if (dst_swapchain)
     {
         /* Handled with regular texture -> swapchain blit */
-        if (src_surface == rt)
+        if (&src_texture->resource == rtv->resource && src_sub_resource_idx == rtv->sub_resource_idx)
             TRACE("Blit from active render target to a swapchain\n");
     }
             TRACE("Blit from active render target to a swapchain\n");
     }
-    else if (src_swapchain && dst_surface == rt)
+    else if (src_swapchain && &dst_texture->resource == rtv->resource
+            && dst_sub_resource_idx == rtv->sub_resource_idx)
     {
         FIXME("Implement blit from a swapchain to the active render target\n");
         return WINED3DERR_INVALIDCALL;
     }
 
     {
         FIXME("Implement blit from a swapchain to the active render target\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if ((src_swapchain || src_surface == rt) && !dst_swapchain)
+    if (!dst_swapchain && (src_swapchain || (&src_texture->resource == rtv->resource
+            && src_sub_resource_idx == rtv->sub_resource_idx)))
     {
         unsigned int src_level, src_width, src_height;
         /* Blit from render target to texture */
     {
         unsigned int src_level, src_width, src_height;
         /* Blit from render target to texture */
@@ -2299,19 +1765,21 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
          *    back buffer. This is slower than reading line per line, thus not used for flipping
          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
          *    pixel by pixel. */
          *    back buffer. This is slower than reading line per line, thus not used for flipping
          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
          *    pixel by pixel. */
-        src_level = surface_get_sub_resource_idx(src_surface) % src_texture->level_count;
+        src_level = src_sub_resource_idx % src_texture->level_count;
         src_width = wined3d_texture_get_level_width(src_texture, src_level);
         src_height = wined3d_texture_get_level_height(src_texture, src_level);
         if (!stretchx || dst_rect->right - dst_rect->left > src_width
                 || dst_rect->bottom - dst_rect->top > src_height)
         {
             TRACE("No stretching in x direction, using direct framebuffer -> texture copy.\n");
         src_width = wined3d_texture_get_level_width(src_texture, src_level);
         src_height = wined3d_texture_get_level_height(src_texture, src_level);
         if (!stretchx || dst_rect->right - dst_rect->left > src_width
                 || dst_rect->bottom - dst_rect->top > src_height)
         {
             TRACE("No stretching in x direction, using direct framebuffer -> texture copy.\n");
-            fb_copy_to_texture_direct(dst_surface, src_surface, src_rect, dst_rect, filter);
+            fb_copy_to_texture_direct(dst_texture, dst_sub_resource_idx, dst_rect,
+                    src_texture, src_sub_resource_idx, src_rect, filter);
         }
         else
         {
             TRACE("Using hardware stretching to flip / stretch the texture.\n");
         }
         else
         {
             TRACE("Using hardware stretching to flip / stretch the texture.\n");
-            fb_copy_to_texture_hwstretch(dst_surface, src_surface, src_rect, dst_rect, filter);
+            fb_copy_to_texture_hwstretch(dst_texture, dst_sub_resource_idx, dst_rect,
+                    src_texture, src_sub_resource_idx, src_rect, filter);
         }
 
         return WINED3D_OK;
         }
 
         return WINED3D_OK;
@@ -2323,12 +1791,9 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
 }
 
 /* Context activation is done by the caller. */
 }
 
 /* Context activation is done by the caller. */
-static BOOL surface_load_sysmem(struct wined3d_surface *surface,
+BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         struct wined3d_context *context, DWORD dst_location)
 {
         struct wined3d_context *context, DWORD dst_location)
 {
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_texture *texture = surface->container;
     struct wined3d_texture_sub_resource *sub_resource;
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
     struct wined3d_texture_sub_resource *sub_resource;
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
@@ -2338,7 +1803,8 @@ static BOOL surface_load_sysmem(struct wined3d_surface *surface,
     if (is_multisample_location(texture, WINED3D_LOCATION_TEXTURE_RGB))
     {
         wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_RB_RESOLVED);
     if (is_multisample_location(texture, WINED3D_LOCATION_TEXTURE_RGB))
     {
         wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_RB_RESOLVED);
-        read_from_framebuffer(surface, context, WINED3D_LOCATION_RB_RESOLVED, dst_location);
+        texture2d_read_from_framebuffer(texture, sub_resource_idx, context,
+                WINED3D_LOCATION_RB_RESOLVED, dst_location);
         return TRUE;
     }
     else
         return TRUE;
     }
     else
@@ -2346,12 +1812,12 @@ static BOOL surface_load_sysmem(struct wined3d_surface *surface,
         if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED))
             wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
 
         if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED))
             wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
 
-        /* Download the surface to system memory. */
+        /* Download the sub-resource to system memory. */
         if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
         {
             wined3d_texture_bind_and_dirtify(texture, context,
                     !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB));
         if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
         {
             wined3d_texture_bind_and_dirtify(texture, context,
                     !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB));
-            surface_download_data(surface, gl_info, dst_location);
+            texture2d_download_data(texture, sub_resource_idx, context, dst_location);
             ++texture->download_count;
 
             return TRUE;
             ++texture->download_count;
 
             return TRUE;
@@ -2361,23 +1827,23 @@ static BOOL surface_load_sysmem(struct wined3d_surface *surface,
     if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
             && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE))
     {
     if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
             && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE))
     {
-        read_from_framebuffer(surface, context, texture->resource.draw_binding, dst_location);
+        texture2d_read_from_framebuffer(texture, sub_resource_idx, context,
+                texture->resource.draw_binding, dst_location);
         return TRUE;
     }
 
         return TRUE;
     }
 
-    FIXME("Can't load surface %p with location flags %s into sysmem.\n",
-            surface, wined3d_debug_location(sub_resource->locations));
+    FIXME("Can't load texture %p, %u with location flags %s into sysmem.\n",
+            texture, sub_resource_idx, wined3d_debug_location(sub_resource->locations));
     return FALSE;
 }
 
 /* Context activation is done by the caller. */
     return FALSE;
 }
 
 /* Context activation is done by the caller. */
-static BOOL surface_load_drawable(struct wined3d_surface *surface,
-        struct wined3d_context *context)
+BOOL texture2d_load_drawable(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, struct wined3d_context *context)
 {
 {
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
-    struct wined3d_surface *restore_rt = NULL;
+    struct wined3d_texture *restore_texture;
     struct wined3d_device *device;
     struct wined3d_device *device;
+    unsigned int restore_idx;
     unsigned int level;
     RECT r;
 
     unsigned int level;
     RECT r;
 
@@ -2392,57 +1858,55 @@ static BOOL surface_load_drawable(struct wined3d_surface *surface,
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
             && wined3d_resource_is_offscreen(&texture->resource))
     {
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
             && wined3d_resource_is_offscreen(&texture->resource))
     {
-        ERR("Trying to load offscreen surface into WINED3D_LOCATION_DRAWABLE.\n");
+        ERR("Trying to load offscreen texture into WINED3D_LOCATION_DRAWABLE.\n");
         return FALSE;
     }
 
     device = texture->resource.device;
         return FALSE;
     }
 
     device = texture->resource.device;
-    restore_rt = context_get_rt_surface(context);
-    if (restore_rt != surface)
+    restore_texture = context->current_rt.texture;
+    restore_idx = context->current_rt.sub_resource_idx;
+    if (restore_texture != texture || restore_idx != sub_resource_idx)
         context = context_acquire(device, texture, sub_resource_idx);
     else
         context = context_acquire(device, texture, sub_resource_idx);
     else
-        restore_rt = NULL;
+        restore_texture = NULL;
 
     level = sub_resource_idx % texture->level_count;
     SetRect(&r, 0, 0, wined3d_texture_get_level_width(texture, level),
             wined3d_texture_get_level_height(texture, level));
     wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
     device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context,
 
     level = sub_resource_idx % texture->level_count;
     SetRect(&r, 0, 0, wined3d_texture_get_level_width(texture, level),
             wined3d_texture_get_level_height(texture, level));
     wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
     device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context,
-            surface, WINED3D_LOCATION_TEXTURE_RGB, &r,
-            surface, WINED3D_LOCATION_DRAWABLE, &r,
+            texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &r,
+            texture, sub_resource_idx, WINED3D_LOCATION_DRAWABLE, &r,
             NULL, WINED3D_TEXF_POINT);
 
             NULL, WINED3D_TEXF_POINT);
 
-    if (restore_rt)
-        context_restore(context, restore_rt);
+    if (restore_texture)
+        context_restore(context, restore_texture, restore_idx);
 
     return TRUE;
 }
 
 
     return TRUE;
 }
 
-static BOOL surface_load_texture(struct wined3d_surface *surface,
+BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         struct wined3d_context *context, BOOL srgb)
 {
     unsigned int width, height, level, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch;
         struct wined3d_context *context, BOOL srgb)
 {
     unsigned int width, height, level, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch;
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_texture *texture = surface->container;
     struct wined3d_device *device = texture->resource.device;
     const struct wined3d_color_key_conversion *conversion;
     struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_device *device = texture->resource.device;
     const struct wined3d_color_key_conversion *conversion;
     struct wined3d_texture_sub_resource *sub_resource;
+    const struct wined3d_format *format;
     struct wined3d_bo_address data;
     BYTE *src_mem, *dst_mem = NULL;
     struct wined3d_bo_address data;
     BYTE *src_mem, *dst_mem = NULL;
-    struct wined3d_format format;
-    POINT dst_point = {0, 0};
-    RECT src_rect;
+    struct wined3d_box src_box;
     BOOL depth;
 
     depth = texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL;
     BOOL depth;
 
     depth = texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL;
-    sub_resource = surface_get_sub_resource(surface);
+    sub_resource = &texture->sub_resources[sub_resource_idx];
 
     if (!depth && wined3d_settings.offscreen_rendering_mode != ORM_FBO
             && wined3d_resource_is_offscreen(&texture->resource)
             && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE))
     {
 
     if (!depth && wined3d_settings.offscreen_rendering_mode != ORM_FBO
             && wined3d_resource_is_offscreen(&texture->resource)
             && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE))
     {
-        surface_load_fb_texture(surface, srgb, context);
+        texture2d_load_fb_texture(texture, sub_resource_idx, srgb, context);
 
         return TRUE;
     }
 
         return TRUE;
     }
@@ -2450,7 +1914,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
     level = sub_resource_idx % texture->level_count;
     width = wined3d_texture_get_level_width(texture, level);
     height = wined3d_texture_get_level_height(texture, level);
     level = sub_resource_idx % texture->level_count;
     width = wined3d_texture_get_level_width(texture, level);
     height = wined3d_texture_get_level_height(texture, level);
-    SetRect(&src_rect, 0, 0, width, height);
+    wined3d_box_set(&src_box, 0, 0, width, height, 0, 1);
 
     if (!depth && sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
             && (texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
 
     if (!depth && sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB)
             && (texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
@@ -2458,12 +1922,17 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
                     &texture->resource, WINED3D_LOCATION_TEXTURE_RGB,
                     &texture->resource, WINED3D_LOCATION_TEXTURE_SRGB))
     {
                     &texture->resource, WINED3D_LOCATION_TEXTURE_RGB,
                     &texture->resource, WINED3D_LOCATION_TEXTURE_SRGB))
     {
+        RECT src_rect;
+
+        SetRect(&src_rect, 0, 0, width, height);
         if (srgb)
         if (srgb)
-            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB,
-                    &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect);
+            texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT,
+                    texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect,
+                    texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect);
         else
         else
-            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB,
-                    &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect);
+            texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT,
+                    texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect,
+                    texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect);
 
         return TRUE;
     }
 
         return TRUE;
     }
@@ -2474,11 +1943,13 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
         DWORD src_location = sub_resource->locations & WINED3D_LOCATION_RB_RESOLVED ?
                 WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE;
         DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
         DWORD src_location = sub_resource->locations & WINED3D_LOCATION_RB_RESOLVED ?
                 WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE;
         DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
+        RECT src_rect;
 
 
+        SetRect(&src_rect, 0, 0, width, height);
         if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info,
                 &texture->resource, src_location, &texture->resource, dst_location))
         if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info,
                 &texture->resource, src_location, &texture->resource, dst_location))
-            surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location,
-                    &src_rect, surface, dst_location, &src_rect);
+            texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT, texture, sub_resource_idx,
+                    src_location, &src_rect, texture, sub_resource_idx, dst_location, &src_rect);
 
         return TRUE;
     }
 
         return TRUE;
     }
@@ -2490,7 +1961,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
         if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_RGB)
         {
         if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_RGB)
         {
-            FIXME_(d3d_perf)("Downloading RGB surface %p to reload it as sRGB.\n", surface);
+            FIXME_(d3d_perf)("Downloading RGB texture %p, %u to reload it as sRGB.\n", texture, sub_resource_idx);
             wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
         }
     }
             wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
         }
     }
@@ -2499,7 +1970,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
         if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_SRGB)
         {
         if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | texture->resource.map_binding))
                 == WINED3D_LOCATION_TEXTURE_SRGB)
         {
-            FIXME_(d3d_perf)("Downloading sRGB surface %p to reload it as RGB.\n", surface);
+            FIXME_(d3d_perf)("Downloading sRGB texture %p, %u to reload it as RGB.\n", texture, sub_resource_idx);
             wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
         }
     }
             wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
         }
     }
@@ -2515,54 +1986,25 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
     wined3d_texture_bind_and_dirtify(texture, context, srgb);
     wined3d_texture_get_pitch(texture, level, &src_row_pitch, &src_slice_pitch);
 
     wined3d_texture_bind_and_dirtify(texture, context, srgb);
     wined3d_texture_get_pitch(texture, level, &src_row_pitch, &src_slice_pitch);
 
-    format = *texture->resource.format;
+    format = texture->resource.format;
     if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
     if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
-        format = *wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage);
+        format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage);
 
     /* Don't use PBOs for converted surfaces. During PBO conversion we look at
      * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
      * getting called. */
 
     /* Don't use PBOs for converted surfaces. During PBO conversion we look at
      * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
      * getting called. */
-#if !defined(STAGING_CSMT)
-    if ((format.conv_byte_count || conversion) && texture->sub_resources[sub_resource_idx].buffer_object)
-#else  /* STAGING_CSMT */
-    if ((format.conv_byte_count || conversion) && texture->sub_resources[sub_resource_idx].buffer)
-#endif /* STAGING_CSMT */
+    if (conversion && sub_resource->buffer_object)
     {
     {
-        TRACE("Removing the pbo attached to surface %p.\n", surface);
+        TRACE("Removing the pbo attached to texture %p, %u.\n", texture, sub_resource_idx);
 
         wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM);
         wined3d_texture_set_map_binding(texture, WINED3D_LOCATION_SYSMEM);
     }
 
     wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->locations);
 
         wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM);
         wined3d_texture_set_map_binding(texture, WINED3D_LOCATION_SYSMEM);
     }
 
     wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->locations);
-    if (format.conv_byte_count)
-    {
-        /* This code is entered for texture formats which need a fixup. */
-        format.byte_count = format.conv_byte_count;
-        wined3d_format_calculate_pitch(&format, 1, width, height, &dst_row_pitch, &dst_slice_pitch);
-
-        src_mem = context_map_bo_address(context, &data, src_slice_pitch,
-                GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
-        if (!(dst_mem = heap_alloc(dst_slice_pitch)))
-        {
-            ERR("Out of memory (%u).\n", dst_slice_pitch);
-            context_release(context);
-            return FALSE;
-        }
-        format.upload(src_mem, dst_mem, src_row_pitch, src_slice_pitch,
-                dst_row_pitch, dst_slice_pitch, width, height, 1);
-        src_row_pitch = dst_row_pitch;
-        context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
-
-        data.buffer_object = 0;
-        data.addr = dst_mem;
-    }
-    else if (conversion)
+    if (conversion)
     {
     {
-        /* This code is only entered for color keying fixups */
-        struct wined3d_palette *palette = NULL;
-
-        wined3d_format_calculate_pitch(&format, device->surface_alignment,
+        wined3d_format_calculate_pitch(format, device->surface_alignment,
                 width, height, &dst_row_pitch, &dst_slice_pitch);
 
         src_mem = context_map_bo_address(context, &data, src_slice_pitch,
                 width, height, &dst_row_pitch, &dst_slice_pitch);
 
         src_mem = context_map_bo_address(context, &data, src_slice_pitch,
@@ -2573,19 +2015,18 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
             context_release(context);
             return FALSE;
         }
             context_release(context);
             return FALSE;
         }
-        if (texture->swapchain && texture->swapchain->palette)
-            palette = texture->swapchain->palette;
         conversion->convert(src_mem, src_row_pitch, dst_mem, dst_row_pitch,
         conversion->convert(src_mem, src_row_pitch, dst_mem, dst_row_pitch,
-                width, height, palette, &texture->async.gl_color_key);
+                width, height, &texture->async.gl_color_key);
         src_row_pitch = dst_row_pitch;
         src_row_pitch = dst_row_pitch;
+        src_slice_pitch = dst_slice_pitch;
         context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
 
         data.buffer_object = 0;
         data.addr = dst_mem;
     }
 
         context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
 
         data.buffer_object = 0;
         data.addr = dst_mem;
     }
 
-    wined3d_surface_upload_data(surface, gl_info, &format, &src_rect,
-            src_row_pitch, &dst_point, srgb, wined3d_const_bo_address(&data));
+    wined3d_texture_upload_data(texture, sub_resource_idx, context, format, &src_box,
+            wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, 0, 0, 0, srgb);
 
     heap_free(dst_mem);
 
 
     heap_free(dst_mem);
 
@@ -2593,17 +2034,18 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
 }
 
 /* Context activation is done by the caller. */
 }
 
 /* Context activation is done by the caller. */
-static BOOL surface_load_renderbuffer(struct wined3d_surface *surface, struct wined3d_context *context,
-        DWORD dst_location)
+BOOL texture2d_load_renderbuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD dst_location)
 {
 {
-    struct wined3d_texture *texture = surface->container;
-    unsigned int level = surface_get_sub_resource_idx(surface) % texture->level_count;
+    unsigned int level = sub_resource_idx % texture->level_count;
     const RECT rect = {0, 0,
             wined3d_texture_get_level_width(texture, level),
             wined3d_texture_get_level_height(texture, level)};
     const RECT rect = {0, 0,
             wined3d_texture_get_level_width(texture, level),
             wined3d_texture_get_level_height(texture, level)};
-    DWORD locations = surface_get_sub_resource(surface)->locations;
-    DWORD src_location;
+    struct wined3d_texture_sub_resource *sub_resource;
+    DWORD src_location, locations;
 
 
+    sub_resource = &texture->sub_resources[sub_resource_idx];
+    locations = sub_resource->locations;
     if (texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
         FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
     if (texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
         FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
@@ -2617,45 +2059,19 @@ static BOOL surface_load_renderbuffer(struct wined3d_surface *surface, struct wi
         src_location = WINED3D_LOCATION_RB_RESOLVED;
     else if (locations & WINED3D_LOCATION_TEXTURE_SRGB)
         src_location = WINED3D_LOCATION_TEXTURE_SRGB;
         src_location = WINED3D_LOCATION_RB_RESOLVED;
     else if (locations & WINED3D_LOCATION_TEXTURE_SRGB)
         src_location = WINED3D_LOCATION_TEXTURE_SRGB;
-    else /* surface_blt_fbo will load the source location if necessary. */
+    else if (locations & WINED3D_LOCATION_TEXTURE_RGB)
+        src_location = WINED3D_LOCATION_TEXTURE_RGB;
+    else if (locations & WINED3D_LOCATION_DRAWABLE)
+        src_location = WINED3D_LOCATION_DRAWABLE;
+    else /* texture2d_blt_fbo() will load the source location if necessary. */
         src_location = WINED3D_LOCATION_TEXTURE_RGB;
 
         src_location = WINED3D_LOCATION_TEXTURE_RGB;
 
-    surface_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT,
-            surface, src_location, &rect, surface, dst_location, &rect);
+    texture2d_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT, texture,
+            sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect);
 
     return TRUE;
 }
 
 
     return TRUE;
 }
 
-/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */
-BOOL surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location)
-{
-    TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location));
-
-    switch (location)
-    {
-        case WINED3D_LOCATION_USER_MEMORY:
-        case WINED3D_LOCATION_SYSMEM:
-        case WINED3D_LOCATION_BUFFER:
-            return surface_load_sysmem(surface, context, location);
-
-        case WINED3D_LOCATION_DRAWABLE:
-            return surface_load_drawable(surface, context);
-
-        case WINED3D_LOCATION_RB_RESOLVED:
-        case WINED3D_LOCATION_RB_MULTISAMPLE:
-            return surface_load_renderbuffer(surface, context, location);
-
-        case WINED3D_LOCATION_TEXTURE_RGB:
-        case WINED3D_LOCATION_TEXTURE_SRGB:
-            return surface_load_texture(surface, context,
-                    location == WINED3D_LOCATION_TEXTURE_SRGB);
-
-        default:
-            ERR("Don't know how to handle location %#x.\n", location);
-            return FALSE;
-    }
-}
-
 /* Context activation is done by the caller. */
 static void fbo_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
 {
 /* Context activation is done by the caller. */
 static void fbo_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
 {
@@ -2679,16 +2095,27 @@ static void fbo_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
 }
 
 static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
 }
 
 static DWORD fbo_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 *colour_key, enum wined3d_texture_filter_type filter)
 {
         const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
 {
-    struct wined3d_resource *src_resource = &src_surface->container->resource;
-    struct wined3d_resource *dst_resource = &dst_surface->container->resource;
-    struct wined3d_device *device = dst_resource->device;
+    struct wined3d_resource *src_resource, *dst_resource;
     enum wined3d_blit_op blit_op = op;
     enum wined3d_blit_op blit_op = op;
+    struct wined3d_device *device;
     struct wined3d_blitter *next;
 
     struct wined3d_blitter *next;
 
+    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), colour_key, debug_d3dtexturefiltertype(filter));
+
+    src_resource = &src_texture->resource;
+    dst_resource = &dst_texture->resource;
+
+    device = dst_resource->device;
+
     if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_resource->format->id == src_resource->format->id)
     {
         if (dst_resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
     if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_resource->format->id == src_resource->format->id)
     {
         if (dst_resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
@@ -2700,23 +2127,30 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
     if (!fbo_blitter_supported(blit_op, context->gl_info,
             src_resource, src_location, dst_resource, dst_location))
     {
     if (!fbo_blitter_supported(blit_op, context->gl_info,
             src_resource, src_location, dst_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, colour_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, colour_key, filter);
     }
 
     if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT)
     {
         TRACE("Colour blit.\n");
     }
 
     if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT)
     {
         TRACE("Colour blit.\n");
-        surface_blt_fbo(device, context, filter, src_surface, src_location,
-                src_rect, dst_surface, dst_location, dst_rect);
+        texture2d_blt_fbo(device, context, filter, src_texture, src_sub_resource_idx, src_location,
+                src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect);
         return dst_location;
     }
 
     if (blit_op == WINED3D_BLIT_OP_DEPTH_BLIT)
     {
         TRACE("Depth/stencil blit.\n");
         return dst_location;
     }
 
     if (blit_op == WINED3D_BLIT_OP_DEPTH_BLIT)
     {
         TRACE("Depth/stencil blit.\n");
-        surface_depth_blt_fbo(device, src_surface, src_location, src_rect, dst_surface, dst_location, dst_rect);
+        texture2d_depth_blt_fbo(device, context, src_texture, src_sub_resource_idx, src_location,
+                src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect);
         return dst_location;
     }
 
         return dst_location;
     }
 
@@ -2779,21 +2213,17 @@ static void raw_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
 
 /* Context activation is done by the caller. */
 static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
 
 /* Context activation is done by the caller. */
 static DWORD raw_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 *colour_key, enum wined3d_texture_filter_type filter)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
         const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    unsigned int src_sub_resource_idx, dst_sub_resource_idx;
     unsigned int src_level, src_layer, dst_level, dst_layer;
     unsigned int src_level, src_layer, dst_level, dst_layer;
-    struct wined3d_texture *src_texture, *dst_texture;
     struct wined3d_blitter *next;
     GLuint src_name, dst_name;
     DWORD location;
 
     struct wined3d_blitter *next;
     GLuint src_name, dst_name;
     DWORD location;
 
-    src_texture = src_surface->container;
-    dst_texture = dst_surface->container;
-
     /* If we would need to copy from a renderbuffer or drawable, we'd probably
      * be better of using the FBO blitter directly, since we'd need to use it
      * to copy the resource contents to the texture anyway. */
     /* If we would need to copy from a renderbuffer or drawable, we'd probably
      * be better of using the FBO blitter directly, since we'd need to use it
      * to copy the resource contents to the texture anyway. */
@@ -2809,17 +2239,15 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
         }
 
         TRACE("Forwarding to blitter %p.\n", next);
         }
 
         TRACE("Forwarding to blitter %p.\n", next);
-        return next->ops->blitter_blit(next, op, context, src_surface, src_location,
-                src_rect, dst_surface, dst_location, dst_rect, colour_key, filter);
+        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, colour_key, filter);
     }
 
     TRACE("Blit using ARB_copy_image.\n");
 
     }
 
     TRACE("Blit using ARB_copy_image.\n");
 
-    src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
     src_level = src_sub_resource_idx % src_texture->level_count;
     src_layer = src_sub_resource_idx / src_texture->level_count;
 
     src_level = src_sub_resource_idx % src_texture->level_count;
     src_layer = src_sub_resource_idx / src_texture->level_count;
 
-    dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
     dst_level = dst_sub_resource_idx % dst_texture->level_count;
     dst_layer = dst_sub_resource_idx / dst_texture->level_count;
 
     dst_level = dst_sub_resource_idx % dst_texture->level_count;
     dst_layer = dst_sub_resource_idx / dst_texture->level_count;
 
@@ -2904,6 +2332,9 @@ static BOOL ffp_blit_supported(enum wined3d_blit_op blit_op, const struct wined3
     const struct wined3d_format *dst_format = dst_resource->format;
     BOOL decompress;
 
     const struct wined3d_format *dst_format = dst_resource->format;
     BOOL decompress;
 
+    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
+        return FALSE;
+
     decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
             && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
     if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
     decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
             && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
     if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
@@ -3038,15 +2469,14 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
 }
 
 static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
 }
 
 static DWORD ffp_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)
 {
         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;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_resource *src_resource, *dst_resource;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_resource *src_resource, *dst_resource;
+    struct wined3d_texture *staging_texture = NULL;
     struct wined3d_color_key old_blt_key;
     struct wined3d_device *device;
     struct wined3d_blitter *next;
     struct wined3d_color_key old_blt_key;
     struct wined3d_device *device;
     struct wined3d_blitter *next;
@@ -3060,28 +2490,66 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
     if (!ffp_blit_supported(op, context, src_resource, src_location, dst_resource, dst_location))
     {
         if ((next = blitter->next))
     if (!ffp_blit_supported(op, context, src_resource, src_location, dst_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);
+            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);
     }
 
     }
 
-    TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
+    TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
+            src_texture, src_sub_resource_idx, dst_texture, dst_sub_resource_idx);
 
     old_blt_key = src_texture->async.src_blt_color_key;
     old_color_key_flags = src_texture->async.color_key_flags;
     wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, color_key);
 
 
     old_blt_key = src_texture->async.src_blt_color_key;
     old_color_key_flags = src_texture->async.color_key_flags;
     wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, color_key);
 
-    /* Make sure the surface is up-to-date. This should probably use
-     * surface_load_location() and worry about the destination surface too,
-     * unless we're overwriting it completely. */
-    wined3d_texture_load(src_texture, context, FALSE);
+    if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+    {
+        struct wined3d_resource_desc desc;
+        struct wined3d_box upload_box;
+        unsigned int src_level;
+        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;
+        }
 
 
-    /* Activate the destination context, set it up for blitting. */
-    context_apply_blit_state(context, device);
+        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
+    {
+        /* Make sure the surface is up-to-date. This should probably use
+         * surface_load_location() and worry about the destination surface
+         * too, unless we're overwriting it completely. */
+        wined3d_texture_load(src_texture, context, FALSE);
+    }
+
+    context_apply_ffp_blit_state(context, device);
 
     if (dst_location == WINED3D_LOCATION_DRAWABLE)
     {
         r = *dst_rect;
 
     if (dst_location == WINED3D_LOCATION_DRAWABLE)
     {
         r = *dst_rect;
-        surface_translate_drawable_coords(dst_surface, context->win_handle, &r);
+        wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &r);
         dst_rect = &r;
     }
 
         dst_rect = &r;
     }
 
@@ -3091,15 +2559,16 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
 
         if (dst_location == WINED3D_LOCATION_DRAWABLE)
         {
 
         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
         {
             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;
         }
             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_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);
         context_set_draw_buffer(context, buffer);
         context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
         context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -3127,7 +2596,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
         checkGLcall("glAlphaFunc");
     }
 
         checkGLcall("glAlphaFunc");
     }
 
-    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);
 
     if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || color_key)
     {
 
     if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || color_key)
     {
@@ -3135,7 +2604,6 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
         checkGLcall("glDisable(GL_ALPHA_TEST)");
     }
 
         checkGLcall("glDisable(GL_ALPHA_TEST)");
     }
 
-    /* Leave the OpenGL state valid for blitting. */
     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
     checkGLcall("glDisable(GL_TEXTURE_2D)");
     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
     checkGLcall("glDisable(GL_TEXTURE_2D)");
     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
@@ -3149,14 +2617,16 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
         checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
     }
 
         checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
     }
 
-    if (wined3d_settings.strict_draw_ordering
-            || (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture))
-        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+    if (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture)
+        gl_info->gl_ops.gl.p_glFlush();
 
     /* Restore the color key parameters */
     wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT,
             (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
 
 
     /* Restore the color key parameters */
     wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT,
             (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
 
+    if (staging_texture)
+        wined3d_texture_decref(staging_texture);
+
     return dst_location;
 }
 
     return dst_location;
 }
 
@@ -3932,16 +3402,13 @@ static void cpu_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
 }
 
 static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
 }
 
 static DWORD cpu_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)
 {
     struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1};
     struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1};
         const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
 {
     struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1};
     struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1};
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    struct wined3d_texture *src_texture = src_surface->container;
     struct wined3d_blt_fx fx;
     DWORD flags = 0;
 
     struct wined3d_blt_fx fx;
     DWORD flags = 0;
 
@@ -3995,17 +3462,12 @@ struct wined3d_blitter *wined3d_cpu_blitter_create(void)
     return blitter;
 }
 
     return blitter;
 }
 
-HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
-        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
-        const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
+HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        const struct wined3d_box *dst_box, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+        const struct wined3d_box *src_box, DWORD flags, const struct wined3d_blt_fx *fx,
+        enum wined3d_texture_filter_type filter)
 {
 {
-    struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1};
-    struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1};
-    unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
-    unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
     struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource;
     struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource;
-    struct wined3d_texture *dst_texture = dst_surface->container;
-    struct wined3d_texture *src_texture = src_surface->container;
     struct wined3d_device *device = dst_texture->resource.device;
     struct wined3d_swapchain *src_swapchain, *dst_swapchain;
     const struct wined3d_color_key *colour_key = NULL;
     struct wined3d_device *device = dst_texture->resource.device;
     struct wined3d_swapchain *src_swapchain, *dst_swapchain;
     const struct wined3d_color_key *colour_key = NULL;
@@ -4014,15 +3476,17 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
     struct wined3d_context *context;
     enum wined3d_blit_op blit_op;
     BOOL scale, convert, resolve;
     struct wined3d_context *context;
     enum wined3d_blit_op blit_op;
     BOOL scale, convert, resolve;
+    RECT src_rect, dst_rect;
 
     static const DWORD simple_blit = WINED3D_BLT_SRC_CKEY
             | WINED3D_BLT_SRC_CKEY_OVERRIDE
             | WINED3D_BLT_ALPHA_TEST
             | WINED3D_BLT_RAW;
 
 
     static const DWORD simple_blit = WINED3D_BLT_SRC_CKEY
             | WINED3D_BLT_SRC_CKEY_OVERRIDE
             | WINED3D_BLT_ALPHA_TEST
             | WINED3D_BLT_RAW;
 
-    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
-            dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect),
-            flags, fx, debug_d3dtexturefiltertype(filter));
+    TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_box %s, src_texture %p, "
+            "src_sub_resource_idx %u, src_box %s, flags %#x, fx %p, filter %s.\n",
+            dst_texture, dst_sub_resource_idx, debug_box(dst_box), src_texture, src_sub_resource_idx,
+            debug_box(src_box), flags, fx, debug_d3dtexturefiltertype(filter));
     TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage));
 
     if (fx)
     TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage));
 
     if (fx)
@@ -4036,6 +3500,9 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
                 fx->src_color_key.color_space_high_value);
     }
 
                 fx->src_color_key.color_space_high_value);
     }
 
+    SetRect(&src_rect, src_box->left, src_box->top, src_box->right, src_box->bottom);
+    SetRect(&dst_rect, dst_box->left, dst_box->top, dst_box->right, dst_box->bottom);
+
     if (!fx || !(fx->fx))
         flags &= ~WINED3D_BLT_FX;
 
     if (!fx || !(fx->fx))
         flags &= ~WINED3D_BLT_FX;
 
@@ -4056,16 +3523,6 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
         goto cpu;
     }
 
         goto cpu;
     }
 
-    /* We want to avoid invalidating the sysmem location for converted
-     * surfaces, since otherwise we'd have to convert the data back when
-     * locking them. */
-    if (dst_texture->flags & WINED3D_TEXTURE_CONVERTED || dst_texture->resource.format->conv_byte_count
-            || wined3d_format_get_color_key_conversion(dst_texture, TRUE))
-    {
-        WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
-        goto cpu;
-    }
-
     if (flags & ~simple_blit)
     {
         WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
     if (flags & ~simple_blit)
     {
         WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
@@ -4086,8 +3543,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
         goto fallback;
     }
 
         goto fallback;
     }
 
-    scale = src_rect->right - src_rect->left != dst_rect->right - dst_rect->left
-            || src_rect->bottom - src_rect->top != dst_rect->bottom - dst_rect->top;
+    scale = src_box->right - src_box->left != dst_box->right - dst_box->left
+            || src_box->bottom - src_box->top != dst_box->bottom - dst_box->top;
     convert = src_texture->resource.format->id != dst_texture->resource.format->id;
     resolve = src_texture->resource.multisample_type != dst_texture->resource.multisample_type;
 
     convert = src_texture->resource.format->id != dst_texture->resource.format->id;
     resolve = src_texture->resource.multisample_type != dst_texture->resource.multisample_type;
 
@@ -4108,8 +3565,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
         context = context_acquire(device, dst_texture, dst_sub_resource_idx);
         valid_locations = device->blitter->ops->blitter_blit(device->blitter,
                 WINED3D_BLIT_OP_DEPTH_BLIT, context,
         context = context_acquire(device, dst_texture, dst_sub_resource_idx);
         valid_locations = device->blitter->ops->blitter_blit(device->blitter,
                 WINED3D_BLIT_OP_DEPTH_BLIT, context,
-                src_surface, src_texture->resource.draw_binding, src_rect,
-                dst_surface, dst_location, dst_rect, NULL, filter);
+                src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect,
+                dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter);
         context_release(context);
 
         wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
         context_release(context);
 
         wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
@@ -4163,19 +3620,16 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
             TRACE("Not doing upload because the destination format needs conversion.\n");
         else
         {
             TRACE("Not doing upload because the destination format needs conversion.\n");
         else
         {
-            POINT dst_point = {dst_rect->left, dst_rect->top};
-
-            if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, src_rect)))
+            wined3d_texture_upload_from_texture(dst_texture, dst_sub_resource_idx, dst_box->left,
+                    dst_box->top, dst_box->front, src_texture, src_sub_resource_idx, src_box);
+            if (!wined3d_resource_is_offscreen(&dst_texture->resource))
             {
             {
-                if (!wined3d_resource_is_offscreen(&dst_texture->resource))
-                {
-                    context = context_acquire(device, dst_texture, dst_sub_resource_idx);
-                    wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
-                            context, dst_texture->resource.draw_binding);
-                    context_release(context);
-                }
-                return WINED3D_OK;
+                context = context_acquire(device, dst_texture, dst_sub_resource_idx);
+                wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
+                        context, dst_texture->resource.draw_binding);
+                context_release(context);
             }
             }
+            return WINED3D_OK;
         }
     }
     else if (dst_swapchain && dst_swapchain->back_buffers
         }
     }
     else if (dst_swapchain && dst_swapchain->back_buffers
@@ -4195,7 +3649,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
         /* Set the swap effect to COPY, we don't want the backbuffer to become
          * undefined. */
         dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
         /* Set the swap effect to COPY, we don't want the backbuffer to become
          * undefined. */
         dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
-        wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0, 0);
+        wined3d_swapchain_present(dst_swapchain, NULL, NULL,
+                dst_swapchain->win_handle, dst_swapchain->swap_interval, 0);
         dst_swapchain->desc.swap_effect = swap_effect;
 
         return WINED3D_OK;
         dst_swapchain->desc.swap_effect = swap_effect;
 
         return WINED3D_OK;
@@ -4212,8 +3667,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
 
     context = context_acquire(device, dst_texture, dst_sub_resource_idx);
     valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context,
 
     context = context_acquire(device, dst_texture, dst_sub_resource_idx);
     valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context,
-            src_surface, src_texture->resource.draw_binding, src_rect,
-            dst_surface, dst_location, dst_rect, colour_key, filter);
+            src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect,
+            dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter);
     context_release(context);
 
     wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
     context_release(context);
 
     wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
@@ -4223,10 +3678,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
 
 fallback:
     /* Special cases for render targets. */
 
 fallback:
     /* Special cases for render targets. */
-    if (SUCCEEDED(surface_blt_special(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter)))
+    if (SUCCEEDED(wined3d_texture_blt_special(dst_texture, dst_sub_resource_idx, &dst_rect,
+            src_texture, src_sub_resource_idx, &src_rect, flags, fx, filter)))
         return WINED3D_OK;
 
 cpu:
         return WINED3D_OK;
 
 cpu:
-    return surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box,
-            src_texture, src_sub_resource_idx, &src_box, flags, fx, filter);
+    return surface_cpu_blt(dst_texture, dst_sub_resource_idx, dst_box,
+            src_texture, src_sub_resource_idx, src_box, flags, fx, filter);
 }
 }
index 8c67a0d..7fee866 100644 (file)
@@ -151,24 +151,20 @@ void CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWN
 
 HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
 
 HRESULT CDECL wined3d_swapchain_present(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)
 {
 {
-    static DWORD notified_flags = 0;
     RECT s, d;
 
     TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, flags %#x.\n",
             swapchain, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
             dst_window_override, flags);
 
     RECT s, d;
 
     TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, flags %#x.\n",
             swapchain, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
             dst_window_override, flags);
 
-    if (flags & ~notified_flags)
-    {
-        FIXME("Ignoring flags %#x.\n", flags & ~notified_flags);
-        notified_flags |= flags;
-    }
+    if (flags)
+        FIXME("Ignoring flags %#x.\n", flags);
 
     if (!swapchain->back_buffers)
     {
 
     if (!swapchain->back_buffers)
     {
-        WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n");
+        WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -318,7 +314,6 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
         struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
 {
     struct wined3d_texture *texture = swapchain->back_buffers[0];
         struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
 {
     struct wined3d_texture *texture = swapchain->back_buffers[0];
-    struct wined3d_surface *back_buffer = texture->sub_resources[0].u.surface;
     struct wined3d_device *device = swapchain->device;
     enum wined3d_texture_filter_type filter;
     DWORD location;
     struct wined3d_device *device = swapchain->device;
     enum wined3d_texture_filter_type filter;
     DWORD location;
@@ -338,8 +333,8 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
         location = WINED3D_LOCATION_RB_RESOLVED;
 
     wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
         location = WINED3D_LOCATION_RB_RESOLVED;
 
     wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
-    device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, back_buffer,
-            location, src_rect, back_buffer, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter);
+    device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, 0,
+            location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter);
     wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
 }
 
     wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
 }
 
@@ -395,6 +390,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
 {
     struct wined3d_texture *back_buffer = swapchain->back_buffers[0];
     const struct wined3d_fb_state *fb = &swapchain->device->cs->fb;
 {
     struct wined3d_texture *back_buffer = swapchain->back_buffers[0];
     const struct wined3d_fb_state *fb = &swapchain->device->cs->fb;
+    struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_texture *logo_texture;
     struct wined3d_context *context;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_texture *logo_texture;
     struct wined3d_context *context;
@@ -480,11 +476,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
     if (swapchain->render_to_fbo)
         swapchain_blit(swapchain, context, src_rect, dst_rect);
 
     if (swapchain->render_to_fbo)
         swapchain_blit(swapchain, context, src_rect, dst_rect);
 
-#if !defined(STAGING_CSMT)
     if (swapchain->num_contexts > 1)
     if (swapchain->num_contexts > 1)
-#else  /* STAGING_CSMT */
-    if (swapchain->num_contexts > 1 && !wined3d_settings.cs_multithreaded)
-#endif /* STAGING_CSMT */
         gl_info->gl_ops.gl.p_glFinish();
 
     /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
         gl_info->gl_ops.gl.p_glFinish();
 
     /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
@@ -523,14 +515,13 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
         wined3d_texture_validate_location(swapchain->back_buffers[swapchain->desc.backbuffer_count - 1],
                 0, WINED3D_LOCATION_DISCARDED);
 
         wined3d_texture_validate_location(swapchain->back_buffers[swapchain->desc.backbuffer_count - 1],
                 0, WINED3D_LOCATION_DISCARDED);
 
-    if (fb->depth_stencil)
+    if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
     {
     {
-        struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(fb->depth_stencil);
+        struct wined3d_texture *ds = texture_from_resource(dsv->resource);
 
 
-        if (ds && (swapchain->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
-                || ds->container->flags & WINED3D_TEXTURE_DISCARD))
-            wined3d_texture_validate_location(ds->container,
-                    fb->depth_stencil->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
+        if ((swapchain->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
+                || ds->flags & WINED3D_TEXTURE_DISCARD))
+            wined3d_texture_validate_location(ds, dsv->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
     }
 
     context_release(context);
     }
 
     context_release(context);
@@ -555,7 +546,7 @@ static const struct wined3d_swapchain_ops swapchain_gl_ops =
 
 static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchain)
 {
 
 static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchain)
 {
-    struct wined3d_surface *front;
+    struct wined3d_dc_info *front;
     POINT offset = {0, 0};
     HDC src_dc, dst_dc;
     RECT draw_rect;
     POINT offset = {0, 0};
     HDC src_dc, dst_dc;
     RECT draw_rect;
@@ -563,11 +554,11 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai
 
     TRACE("swapchain %p.\n", swapchain);
 
 
     TRACE("swapchain %p.\n", swapchain);
 
-    front = swapchain->front_buffer->sub_resources[0].u.surface;
+    front = &swapchain->front_buffer->dc_info[0];
     if (swapchain->palette)
         wined3d_palette_apply_to_dc(swapchain->palette, front->dc);
 
     if (swapchain->palette)
         wined3d_palette_apply_to_dc(swapchain->palette, front->dc);
 
-    if (front->container->resource.map_count)
+    if (swapchain->front_buffer->resource.map_count)
         ERR("Trying to blit a mapped surface.\n");
 
     TRACE("Copying surface %p to screen.\n", front);
         ERR("Trying to blit a mapped surface.\n");
 
     TRACE("Copying surface %p to screen.\n", front);
@@ -598,26 +589,26 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai
 static void swapchain_gdi_present(struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, DWORD flags)
 {
 static void swapchain_gdi_present(struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, DWORD flags)
 {
-    struct wined3d_surface *front, *back;
+    struct wined3d_dc_info *front, *back;
     HBITMAP bitmap;
     void *data;
     HDC dc;
 
     HBITMAP bitmap;
     void *data;
     HDC dc;
 
-    front = swapchain->front_buffer->sub_resources[0].u.surface;
-    back = swapchain->back_buffers[0]->sub_resources[0].u.surface;
+    front = &swapchain->front_buffer->dc_info[0];
+    back = &swapchain->back_buffers[0]->dc_info[0];
 
     /* Flip the surface data. */
     dc = front->dc;
     bitmap = front->bitmap;
 
     /* Flip the surface data. */
     dc = front->dc;
     bitmap = front->bitmap;
-    data = front->container->resource.heap_memory;
+    data = swapchain->front_buffer->resource.heap_memory;
 
     front->dc = back->dc;
     front->bitmap = back->bitmap;
 
     front->dc = back->dc;
     front->bitmap = back->bitmap;
-    front->container->resource.heap_memory = back->container->resource.heap_memory;
+    swapchain->front_buffer->resource.heap_memory = swapchain->back_buffers[0]->resource.heap_memory;
 
     back->dc = dc;
     back->bitmap = bitmap;
 
     back->dc = dc;
     back->bitmap = bitmap;
-    back->container->resource.heap_memory = data;
+    swapchain->back_buffers[0]->resource.heap_memory = data;
 
     /* FPS support */
     if (TRACE_ON(fps))
 
     /* FPS support */
     if (TRACE_ON(fps))
@@ -686,44 +677,26 @@ static void wined3d_swapchain_apply_sample_count_override(const struct wined3d_s
     *quality = 0;
 }
 
     *quality = 0;
 }
 
-static void wined3d_swapchain_update_swap_interval_cs(void *object)
+void wined3d_swapchain_set_swap_interval(struct wined3d_swapchain *swapchain,
+        unsigned int swap_interval)
 {
 {
-    struct wined3d_swapchain *swapchain = object;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
-    int swap_interval;
+
+    swap_interval = swap_interval <= 4 ? swap_interval : 1;
+    if (swapchain->swap_interval == swap_interval)
+        return;
+
+    swapchain->swap_interval = swap_interval;
 
     context = context_acquire(swapchain->device, swapchain->front_buffer, 0);
     gl_info = context->gl_info;
 
 
     context = context_acquire(swapchain->device, swapchain->front_buffer, 0);
     gl_info = context->gl_info;
 
-    switch (swapchain->desc.swap_interval)
-    {
-        case WINED3DPRESENT_INTERVAL_IMMEDIATE:
-            swap_interval = 0;
-            break;
-        case WINED3DPRESENT_INTERVAL_DEFAULT:
-        case WINED3DPRESENT_INTERVAL_ONE:
-            swap_interval = 1;
-            break;
-        case WINED3DPRESENT_INTERVAL_TWO:
-            swap_interval = 2;
-            break;
-        case WINED3DPRESENT_INTERVAL_THREE:
-            swap_interval = 3;
-            break;
-        case WINED3DPRESENT_INTERVAL_FOUR:
-            swap_interval = 4;
-            break;
-        default:
-            FIXME("Unhandled present interval %#x.\n", swapchain->desc.swap_interval);
-            swap_interval = 1;
-    }
-
     if (gl_info->supported[WGL_EXT_SWAP_CONTROL])
     {
         if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval)))
     if (gl_info->supported[WGL_EXT_SWAP_CONTROL])
     {
         if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval)))
-            ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x\n",
-                swap_interval, context, GetLastError());
+            ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x.\n",
+                    swap_interval, context, GetLastError());
     }
 
     context_release(context);
     }
 
     context_release(context);
@@ -769,8 +742,12 @@ static void wined3d_swapchain_cs_init(void *object)
         FIXME("Add OpenGL context recreation support.\n");
 
     context_release(swapchain->context[0]);
         FIXME("Add OpenGL context recreation support.\n");
 
     context_release(swapchain->context[0]);
+}
 
 
-    wined3d_swapchain_update_swap_interval_cs(swapchain);
+void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, const struct wined3d_device *device)
+{
+    /* Subtract 1 for the implicit OpenGL latency. */
+    swapchain->max_frame_latency = device->max_frame_latency >= 2 ? device->max_frame_latency - 1 : 1;
 }
 
 static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
 }
 
 static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
@@ -781,9 +758,9 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
     BOOL displaymode_set = FALSE;
     DWORD texture_flags = 0;
     RECT client_rect;
     BOOL displaymode_set = FALSE;
     DWORD texture_flags = 0;
     RECT client_rect;
+    unsigned int i;
     HWND window;
     HRESULT hr;
     HWND window;
     HRESULT hr;
-    UINT i;
 
     if (desc->backbuffer_count > 1)
     {
 
     if (desc->backbuffer_count > 1)
     {
@@ -809,6 +786,8 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
     swapchain->ref = 1;
     swapchain->win_handle = window;
     swapchain->device_window = window;
     swapchain->ref = 1;
     swapchain->win_handle = window;
     swapchain->device_window = window;
+    swapchain->swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT;
+    swapchain_set_max_frame_latency(swapchain, device);
 
     if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
             adapter->ordinal, &swapchain->original_mode, NULL)))
 
     if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
             adapter->ordinal, &swapchain->original_mode, NULL)))
@@ -821,15 +800,16 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
     GetClientRect(window, &client_rect);
     if (desc->windowed)
     {
     GetClientRect(window, &client_rect);
     if (desc->windowed)
     {
+        TRACE("Client rect %s.\n", wine_dbgstr_rect(&client_rect));
+
         if (!desc->backbuffer_width)
         {
         if (!desc->backbuffer_width)
         {
-            desc->backbuffer_width = client_rect.right;
+            desc->backbuffer_width = client_rect.right ? client_rect.right : 8;
             TRACE("Updating width to %u.\n", desc->backbuffer_width);
         }
             TRACE("Updating width to %u.\n", desc->backbuffer_width);
         }
-
         if (!desc->backbuffer_height)
         {
         if (!desc->backbuffer_height)
         {
-            desc->backbuffer_height = client_rect.bottom;
+            desc->backbuffer_height = client_rect.bottom ? client_rect.bottom : 8;
             TRACE("Updating height to %u.\n", desc->backbuffer_height);
         }
 
             TRACE("Updating height to %u.\n", desc->backbuffer_height);
         }
 
@@ -1141,11 +1121,6 @@ void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain)
     }
 }
 
     }
 }
 
-void swapchain_update_swap_interval(struct wined3d_swapchain *swapchain)
-{
-    wined3d_cs_init_object(swapchain->device->cs, wined3d_swapchain_update_swap_interval_cs, swapchain);
-}
-
 void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate)
 {
     struct wined3d_device *device = swapchain->device;
 void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate)
 {
     struct wined3d_device *device = swapchain->device;
index e6af0c7..bee7f35 100644 (file)
@@ -30,6 +30,20 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 #define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
 
 
 #define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
 
+struct wined3d_texture_idx
+{
+    struct wined3d_texture *texture;
+    unsigned int sub_resource_idx;
+};
+
+struct wined3d_rect_f
+{
+    float l;
+    float t;
+    float r;
+    float b;
+};
+
 static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
 {
     return !(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU)
 static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
 {
     return !(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU)
@@ -48,6 +62,32 @@ static BOOL wined3d_texture_use_immutable_storage(const struct wined3d_texture *
             && !(texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE);
 }
 
             && !(texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE);
 }
 
+/* Front buffer coordinates are always full screen coordinates, but our GL
+ * drawable is limited to the window's client area. The sysmem and texture
+ * copies do have the full screen size. Note that GL has a bottom-left
+ * origin, while D3D has a top-left origin. */
+void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect)
+{
+    unsigned int drawable_height;
+    POINT offset = {0, 0};
+    RECT windowsize;
+
+    if (!texture->swapchain)
+        return;
+
+    if (texture == texture->swapchain->front_buffer)
+    {
+        ScreenToClient(window, &offset);
+        OffsetRect(rect, offset.x, offset.y);
+    }
+
+    GetClientRect(window, &windowsize);
+    drawable_height = windowsize.bottom - windowsize.top;
+
+    rect->top = drawable_height - rect->top;
+    rect->bottom = drawable_height - rect->bottom;
+}
+
 GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture)
 {
     const struct wined3d_swapchain *swapchain = texture->swapchain;
 GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture)
 {
     const struct wined3d_swapchain *swapchain = texture->swapchain;
@@ -101,9 +141,120 @@ static DWORD wined3d_resource_access_from_location(DWORD location)
     }
 }
 
     }
 }
 
-static BOOL is_power_of_two(UINT x)
+static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct wined3d_rect_f *f)
+{
+    f->l = ((r->left * 2.0f) / w) - 1.0f;
+    f->t = ((r->top * 2.0f) / h) - 1.0f;
+    f->r = ((r->right * 2.0f) / w) - 1.0f;
+    f->b = ((r->bottom * 2.0f) / h) - 1.0f;
+}
+
+void texture2d_get_blt_info(const struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, const RECT *rect, struct wined3d_blt_info *info)
 {
 {
-    return (x != 0) && !(x & (x - 1));
+    struct wined3d_vec3 *coords = info->texcoords;
+    struct wined3d_rect_f f;
+    unsigned int level;
+    GLenum target;
+    GLsizei w, h;
+
+    level = sub_resource_idx % texture->level_count;
+    w = wined3d_texture_get_level_pow2_width(texture, level);
+    h = wined3d_texture_get_level_pow2_height(texture, level);
+    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
+
+    switch (target)
+    {
+        default:
+            FIXME("Unsupported texture target %#x.\n", target);
+            /* Fall back to GL_TEXTURE_2D */
+        case GL_TEXTURE_2D:
+            info->bind_target = GL_TEXTURE_2D;
+            coords[0].x = (float)rect->left / w;
+            coords[0].y = (float)rect->top / h;
+            coords[0].z = 0.0f;
+
+            coords[1].x = (float)rect->right / w;
+            coords[1].y = (float)rect->top / h;
+            coords[1].z = 0.0f;
+
+            coords[2].x = (float)rect->left / w;
+            coords[2].y = (float)rect->bottom / h;
+            coords[2].z = 0.0f;
+
+            coords[3].x = (float)rect->right / w;
+            coords[3].y = (float)rect->bottom / h;
+            coords[3].z = 0.0f;
+            break;
+
+        case GL_TEXTURE_RECTANGLE_ARB:
+            info->bind_target = GL_TEXTURE_RECTANGLE_ARB;
+            coords[0].x = rect->left;  coords[0].y = rect->top;    coords[0].z = 0.0f;
+            coords[1].x = rect->right; coords[1].y = rect->top;    coords[1].z = 0.0f;
+            coords[2].x = rect->left;  coords[2].y = rect->bottom; coords[2].z = 0.0f;
+            coords[3].x = rect->right; coords[3].y = rect->bottom; coords[3].z = 0.0f;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x =  1.0f;   coords[0].y = -f.t;   coords[0].z = -f.l;
+            coords[1].x =  1.0f;   coords[1].y = -f.t;   coords[1].z = -f.r;
+            coords[2].x =  1.0f;   coords[2].y = -f.b;   coords[2].z = -f.l;
+            coords[3].x =  1.0f;   coords[3].y = -f.b;   coords[3].z = -f.r;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x = -1.0f;   coords[0].y = -f.t;   coords[0].z = f.l;
+            coords[1].x = -1.0f;   coords[1].y = -f.t;   coords[1].z = f.r;
+            coords[2].x = -1.0f;   coords[2].y = -f.b;   coords[2].z = f.l;
+            coords[3].x = -1.0f;   coords[3].y = -f.b;   coords[3].z = f.r;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x = f.l;   coords[0].y =  1.0f;   coords[0].z = f.t;
+            coords[1].x = f.r;   coords[1].y =  1.0f;   coords[1].z = f.t;
+            coords[2].x = f.l;   coords[2].y =  1.0f;   coords[2].z = f.b;
+            coords[3].x = f.r;   coords[3].y =  1.0f;   coords[3].z = f.b;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x = f.l;   coords[0].y = -1.0f;   coords[0].z = -f.t;
+            coords[1].x = f.r;   coords[1].y = -1.0f;   coords[1].z = -f.t;
+            coords[2].x = f.l;   coords[2].y = -1.0f;   coords[2].z = -f.b;
+            coords[3].x = f.r;   coords[3].y = -1.0f;   coords[3].z = -f.b;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x = f.l;   coords[0].y = -f.t;   coords[0].z =  1.0f;
+            coords[1].x = f.r;   coords[1].y = -f.t;   coords[1].z =  1.0f;
+            coords[2].x = f.l;   coords[2].y = -f.b;   coords[2].z =  1.0f;
+            coords[3].x = f.r;   coords[3].y = -f.b;   coords[3].z =  1.0f;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0].x = -f.l;   coords[0].y = -f.t;   coords[0].z = -1.0f;
+            coords[1].x = -f.r;   coords[1].y = -f.t;   coords[1].z = -1.0f;
+            coords[2].x = -f.l;   coords[2].y = -f.b;   coords[2].z = -1.0f;
+            coords[3].x = -f.r;   coords[3].y = -f.b;   coords[3].z = -1.0f;
+            break;
+    }
 }
 
 static void wined3d_texture_evict_sysmem(struct wined3d_texture *texture)
 }
 
 static void wined3d_texture_evict_sysmem(struct wined3d_texture *texture)
@@ -294,11 +445,7 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su
     if (locations & WINED3D_LOCATION_BUFFER)
     {
         data->addr = NULL;
     if (locations & WINED3D_LOCATION_BUFFER)
     {
         data->addr = NULL;
-#if !defined(STAGING_CSMT)
         data->buffer_object = sub_resource->buffer_object;
         data->buffer_object = sub_resource->buffer_object;
-#else  /* STAGING_CSMT */
-        data->buffer_object = sub_resource->buffer->name;
-#endif /* STAGING_CSMT */
         return;
     }
     if (locations & WINED3D_LOCATION_USER_MEMORY)
         return;
     }
     if (locations & WINED3D_LOCATION_USER_MEMORY)
@@ -320,93 +467,8 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su
     data->buffer_object = 0;
 }
 
     data->buffer_object = 0;
 }
 
-static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops,
-        UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, DWORD flags,
-        struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops,
-        const struct wined3d_resource_ops *resource_ops)
-{
-    unsigned int i, j, size, offset = 0;
-    const struct wined3d_format *format;
-    HRESULT hr;
-
-    TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, "
-            "multisample_type %#x, multisample_quality %#x, usage %s, access %s, width %u, height %u, depth %u, "
-            "flags %#x, device %p, parent %p, parent_ops %p, resource_ops %p.\n",
-            texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type),
-            debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality,
-            debug_d3dusage(desc->usage), wined3d_debug_resource_access(desc->access),
-            desc->width, desc->height, desc->depth, flags, device, parent, parent_ops, resource_ops);
-
-    if (!desc->width || !desc->height || !desc->depth)
-        return WINED3DERR_INVALIDCALL;
-
-    format = wined3d_get_format(&device->adapter->gl_info, desc->format, desc->usage);
-
-    for (i = 0; i < layer_count; ++i)
-    {
-        for (j = 0; j < level_count; ++j)
-        {
-            unsigned int idx = i * level_count + j;
-
-            size = wined3d_format_calculate_size(format, device->surface_alignment,
-                    max(1, desc->width >> j), max(1, desc->height >> j), max(1, desc->depth >> j));
-            texture->sub_resources[idx].offset = offset;
-            texture->sub_resources[idx].size = size;
-            offset += size;
-        }
-        offset = (offset + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1);
-    }
-
-    if (!offset)
-        return WINED3DERR_INVALIDCALL;
-
-    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
-            desc->multisample_type, desc->multisample_quality, desc->usage, desc->access,
-            desc->width, desc->height, desc->depth, offset, parent, parent_ops, resource_ops)))
-    {
-        static unsigned int once;
-
-        /* DXTn 3D textures are not supported. Do not write the ERR for them. */
-        if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3
-                || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5)
-                && !(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE)
-                && desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !once++)
-            ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n");
-
-        WARN("Failed to initialize resource, returning %#x\n", hr);
-        return hr;
-    }
-    wined3d_resource_update_draw_binding(&texture->resource);
-    if ((flags & WINED3D_TEXTURE_CREATE_MAPPABLE) || desc->format == WINED3DFMT_D16_LOCKABLE)
-        texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
-
-    texture->texture_ops = texture_ops;
-
-    texture->layer_count = layer_count;
-    texture->level_count = level_count;
-    texture->lod = 0;
-    texture->flags |= WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS;
-    if (flags & WINED3D_TEXTURE_CREATE_GET_DC_LENIENT)
-        texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_GET_DC_LENIENT;
-    if (flags & (WINED3D_TEXTURE_CREATE_GET_DC | WINED3D_TEXTURE_CREATE_GET_DC_LENIENT))
-        texture->flags |= WINED3D_TEXTURE_GET_DC;
-    if (flags & WINED3D_TEXTURE_CREATE_DISCARD)
-        texture->flags |= WINED3D_TEXTURE_DISCARD;
-    if (flags & WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS)
-    {
-        if (!(texture->resource.format_flags & WINED3DFMT_FLAG_GEN_MIPMAP))
-            WARN("Format doesn't support mipmaps generation, "
-                    "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n");
-        else
-            texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS;
-    }
-
-    return WINED3D_OK;
-}
-
 /* Context activation is done by the caller. */
 static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
 /* Context activation is done by the caller. */
 static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
-#if !defined(STAGING_CSMT)
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
 {
     GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object;
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
 {
     GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object;
@@ -419,19 +481,6 @@ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture
 
     wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
     *buffer_object = 0;
 
     wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
     *buffer_object = 0;
-#else  /* STAGING_CSMT */
-        unsigned int sub_resource_idx, struct wined3d_context *context)
-{
-    struct wined3d_gl_bo *buffer = texture->sub_resources[sub_resource_idx].buffer;
-    GLuint name = buffer->name;
-
-    wined3d_device_release_bo(texture->resource.device, buffer, context);
-    texture->sub_resources[sub_resource_idx].buffer = NULL;
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
-
-    TRACE("Deleted buffer object %u for texture %p, sub-resource %u.\n",
-            name, texture, sub_resource_idx);
-#endif /* STAGING_CSMT */
 }
 
 static void wined3d_texture_update_map_binding(struct wined3d_texture *texture)
 }
 
 static void wined3d_texture_update_map_binding(struct wined3d_texture *texture)
@@ -451,11 +500,7 @@ static void wined3d_texture_update_map_binding(struct wined3d_texture *texture)
                 && !wined3d_texture_load_location(texture, i, context, map_binding))
             ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding));
         if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER)
                 && !wined3d_texture_load_location(texture, i, context, map_binding))
             ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding));
         if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER)
-#if !defined(STAGING_CSMT)
             wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
             wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
-#else  /* STAGING_CSMT */
-            wined3d_texture_remove_buffer_object(texture, i, context);
-#endif /* STAGING_CSMT */
     }
 
     if (context)
     }
 
     if (context)
@@ -520,11 +565,14 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture *
         const struct wined3d_gl_info *gl_info)
 {
     unsigned int level, level_count, layer, layer_count;
         const struct wined3d_gl_info *gl_info)
 {
     unsigned int level, level_count, layer, layer_count;
-    GLsizei width, height;
+    GLsizei width, height, depth;
     GLenum target;
 
     level_count = texture->level_count;
     GLenum target;
 
     level_count = texture->level_count;
-    layer_count = texture->target == GL_TEXTURE_2D_ARRAY ? 1 : texture->layer_count;
+    if (texture->target == GL_TEXTURE_1D_ARRAY || texture->target == GL_TEXTURE_2D_ARRAY)
+        layer_count = 1;
+    else
+        layer_count = texture->layer_count;
 
     for (layer = 0; layer < layer_count; ++layer)
     {
 
     for (layer = 0; layer < layer_count; ++layer)
     {
@@ -543,16 +591,24 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture *
             TRACE("texture %p, layer %u, level %u, target %#x, width %u, height %u.\n",
                     texture, layer, level, target, width, height);
 
             TRACE("texture %p, layer %u, level %u, target %#x, width %u, height %u.\n",
                     texture, layer, level, target, width, height);
 
-            if (texture->target == GL_TEXTURE_2D_ARRAY)
+            if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY)
             {
             {
+                depth = wined3d_texture_get_level_depth(texture, level);
                 GL_EXTCALL(glTexImage3D(target, level, gl_internal_format, width, height,
                 GL_EXTCALL(glTexImage3D(target, level, gl_internal_format, width, height,
-                        texture->layer_count, 0, format->glFormat, format->glType, NULL));
+                        target == GL_TEXTURE_2D_ARRAY ? texture->layer_count : depth, 0,
+                        format->glFormat, format->glType, NULL));
                 checkGLcall("glTexImage3D");
             }
                 checkGLcall("glTexImage3D");
             }
+            else if (target == GL_TEXTURE_1D)
+            {
+                gl_info->gl_ops.gl.p_glTexImage1D(target, level, gl_internal_format,
+                        width, 0, format->glFormat, format->glType, NULL);
+            }
             else
             {
             else
             {
-                gl_info->gl_ops.gl.p_glTexImage2D(target, level, gl_internal_format,
-                        width, height, 0, format->glFormat, format->glType, NULL);
+                gl_info->gl_ops.gl.p_glTexImage2D(target, level, gl_internal_format, width,
+                        target == GL_TEXTURE_1D_ARRAY ? texture->layer_count : height, 0,
+                        format->glFormat, format->glType, NULL);
                 checkGLcall("glTexImage2D");
             }
         }
                 checkGLcall("glTexImage2D");
             }
         }
@@ -570,6 +626,10 @@ static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture
 
     switch (texture->target)
     {
 
     switch (texture->target)
     {
+        case GL_TEXTURE_3D:
+            GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count,
+                    gl_internal_format, width, height, wined3d_texture_get_level_depth(texture, 0)));
+            break;
         case GL_TEXTURE_2D_ARRAY:
             GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count,
                     gl_internal_format, width, height, texture->layer_count));
         case GL_TEXTURE_2D_ARRAY:
             GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count,
                     gl_internal_format, width, height, texture->layer_count));
@@ -582,6 +642,13 @@ static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture
             GL_EXTCALL(glTexStorage3DMultisample(texture->target, samples,
                     gl_internal_format, width, height, texture->layer_count, GL_FALSE));
             break;
             GL_EXTCALL(glTexStorage3DMultisample(texture->target, samples,
                     gl_internal_format, width, height, texture->layer_count, GL_FALSE));
             break;
+        case GL_TEXTURE_1D_ARRAY:
+            GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count,
+                    gl_internal_format, width, texture->layer_count));
+            break;
+        case GL_TEXTURE_1D:
+            GL_EXTCALL(glTexStorage1D(texture->target, texture->level_count, gl_internal_format, width));
+            break;
         default:
             GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count,
                     gl_internal_format, width, height));
         default:
             GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count,
                     gl_internal_format, width, height));
@@ -651,56 +718,185 @@ static void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *text
     }
 }
 
     }
 }
 
+static void wined3d_texture_create_dc(void *object)
+{
+    const struct wined3d_texture_idx *idx = object;
+    struct wined3d_context *context = NULL;
+    unsigned int sub_resource_idx, level;
+    const struct wined3d_format *format;
+    unsigned int row_pitch, slice_pitch;
+    struct wined3d_texture *texture;
+    struct wined3d_dc_info *dc_info;
+    struct wined3d_bo_address data;
+    D3DKMT_CREATEDCFROMMEMORY desc;
+    struct wined3d_device *device;
+    NTSTATUS status;
+
+    TRACE("texture %p, sub_resource_idx %u.\n", idx->texture, idx->sub_resource_idx);
+
+    texture = idx->texture;
+    sub_resource_idx = idx->sub_resource_idx;
+    level = sub_resource_idx % texture->level_count;
+    device = texture->resource.device;
+
+    format = texture->resource.format;
+    if (!format->ddi_format)
+    {
+        WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
+        return;
+    }
+
+    if (!texture->dc_info)
+    {
+        unsigned int sub_count = texture->level_count * texture->layer_count;
+
+        if (!(texture->dc_info = heap_calloc(sub_count, sizeof(*texture->dc_info))))
+        {
+            ERR("Failed to allocate DC info.\n");
+            return;
+        }
+    }
+
+    if (device->d3d_initialized)
+        context = context_acquire(device, NULL, 0);
+
+    wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
+    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
+    wined3d_texture_get_pitch(texture, level, &row_pitch, &slice_pitch);
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
+    desc.pMemory = context_map_bo_address(context, &data,
+            texture->sub_resources[sub_resource_idx].size,
+            GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
+
+    if (context)
+        context_release(context);
+
+    desc.Format = format->ddi_format;
+    desc.Width = wined3d_texture_get_level_width(texture, level);
+    desc.Height = wined3d_texture_get_level_height(texture, level);
+    desc.Pitch = row_pitch;
+    desc.hDeviceDc = CreateCompatibleDC(NULL);
+    desc.pColorTable = NULL;
+
+    status = D3DKMTCreateDCFromMemory(&desc);
+    DeleteDC(desc.hDeviceDc);
+    if (status)
+    {
+        WARN("Failed to create DC, status %#x.\n", status);
+        return;
+    }
+
+    dc_info = &texture->dc_info[sub_resource_idx];
+    dc_info->dc = desc.hDc;
+    dc_info->bitmap = desc.hBitmap;
+
+    TRACE("Created DC %p, bitmap %p for texture %p, %u.\n", dc_info->dc, dc_info->bitmap, texture, sub_resource_idx);
+}
+
+static void wined3d_texture_destroy_dc(void *object)
+{
+    const struct wined3d_texture_idx *idx = object;
+    D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
+    struct wined3d_context *context = NULL;
+    struct wined3d_texture *texture;
+    struct wined3d_dc_info *dc_info;
+    struct wined3d_bo_address data;
+    unsigned int sub_resource_idx;
+    struct wined3d_device *device;
+    NTSTATUS status;
+
+    texture = idx->texture;
+    sub_resource_idx = idx->sub_resource_idx;
+    device = texture->resource.device;
+    dc_info = &texture->dc_info[sub_resource_idx];
+
+    if (!dc_info->dc)
+    {
+        ERR("Sub-resource {%p, %u} has no DC.\n", texture, sub_resource_idx);
+        return;
+    }
+
+    TRACE("dc %p, bitmap %p.\n", dc_info->dc, dc_info->bitmap);
+
+    destroy_desc.hDc = dc_info->dc;
+    destroy_desc.hBitmap = dc_info->bitmap;
+    if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
+        ERR("Failed to destroy dc, status %#x.\n", status);
+    dc_info->dc = NULL;
+    dc_info->bitmap = NULL;
+
+    if (device->d3d_initialized)
+        context = context_acquire(device, NULL, 0);
+
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
+    context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
+
+    if (context)
+        context_release(context);
+}
+
 static void wined3d_texture_cleanup(struct wined3d_texture *texture)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
     struct wined3d_device *device = texture->resource.device;
 static void wined3d_texture_cleanup(struct wined3d_texture *texture)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
     struct wined3d_device *device = texture->resource.device;
+    struct wined3d_renderbuffer_entry *entry, *entry2;
+    const struct wined3d_gl_info *gl_info = NULL;
     struct wined3d_context *context = NULL;
     struct wined3d_context *context = NULL;
-#if !defined(STAGING_CSMT)
-    const struct wined3d_gl_info *gl_info;
+    struct wined3d_dc_info *dc_info;
     GLuint buffer_object;
     GLuint buffer_object;
-#else  /* STAGING_CSMT */
-    struct wined3d_gl_bo *buffer;
-#endif /* STAGING_CSMT */
     unsigned int i;
 
     TRACE("texture %p.\n", texture);
 
     for (i = 0; i < sub_count; ++i)
     {
     unsigned int i;
 
     TRACE("texture %p.\n", texture);
 
     for (i = 0; i < sub_count; ++i)
     {
-#if !defined(STAGING_CSMT)
         if (!(buffer_object = texture->sub_resources[i].buffer_object))
             continue;
 
         TRACE("Deleting buffer object %u.\n", buffer_object);
         if (!(buffer_object = texture->sub_resources[i].buffer_object))
             continue;
 
         TRACE("Deleting buffer object %u.\n", buffer_object);
-#else  /* STAGING_CSMT */
-        if (!(buffer = texture->sub_resources[i].buffer))
-            continue;
-
-        TRACE("Deleting buffer object %u.\n", buffer->name);
-#endif /* STAGING_CSMT */
 
         /* We may not be able to get a context in wined3d_texture_cleanup() in
          * general, but if a buffer object was previously created we can. */
         if (!context)
 
         /* We may not be able to get a context in wined3d_texture_cleanup() in
          * general, but if a buffer object was previously created we can. */
         if (!context)
-#if !defined(STAGING_CSMT)
         {
             context = context_acquire(device, NULL, 0);
             gl_info = context->gl_info;
         }
 
         GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
         {
             context = context_acquire(device, NULL, 0);
             gl_info = context->gl_info;
         }
 
         GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
-#else  /* STAGING_CSMT */
-            context = context_acquire(device, NULL, 0);
+    }
+
+    if (!context && !list_empty(&texture->renderbuffers))
+    {
+        context = context_acquire(device, NULL, 0);
+        gl_info = context->gl_info;
+    }
 
 
-        wined3d_device_release_bo(device, buffer, context);
-        texture->sub_resources[i].buffer = NULL;
-#endif /* STAGING_CSMT */
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        TRACE("Deleting renderbuffer %u.\n", entry->id);
+        context_gl_resource_released(device, entry->id, TRUE);
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+        heap_free(entry);
     }
     }
+
     if (context)
         context_release(context);
 
     if (context)
         context_release(context);
 
-    texture->texture_ops->texture_cleanup_sub_resources(texture);
+    if ((dc_info = texture->dc_info))
+    {
+        for (i = 0; i < sub_count; ++i)
+        {
+            if (dc_info[i].dc)
+            {
+                struct wined3d_texture_idx texture_idx = {texture, i};
+
+                wined3d_texture_destroy_dc(&texture_idx);
+            }
+        }
+        heap_free(dc_info);
+    }
+
     if (texture->overlay_info)
     {
         for (i = 0; i < sub_count; ++i)
     if (texture->overlay_info)
     {
         for (i = 0; i < sub_count; ++i)
@@ -1252,105 +1448,87 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
     return WINED3D_OK;
 }
 
     return WINED3D_OK;
 }
 
-static void texture2d_create_dc(void *object)
+/* In D3D the depth stencil dimensions have to be greater than or equal to the
+ * render target dimensions. With FBOs, the dimensions have to be an exact match. */
+/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
+/* Context activation is done by the caller. */
+void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
+        unsigned int level, const struct wined3d_rendertarget_info *rt)
 {
 {
-    struct wined3d_surface *surface = object;
-    struct wined3d_context *context = NULL;
-    const struct wined3d_format *format;
-    unsigned int row_pitch, slice_pitch;
-    struct wined3d_texture *texture;
-    struct wined3d_bo_address data;
-    D3DKMT_CREATEDCFROMMEMORY desc;
-    unsigned int sub_resource_idx;
-    struct wined3d_device *device;
-    NTSTATUS status;
+    struct wined3d_renderbuffer_entry *entry;
+    const struct wined3d_gl_info *gl_info;
+    unsigned int src_width, src_height;
+    unsigned int width, height;
+    GLuint renderbuffer = 0;
 
 
-    TRACE("surface %p.\n", surface);
+    gl_info = &texture->resource.device->adapter->gl_info;
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
+        return;
 
 
-    texture = surface->container;
-    sub_resource_idx = surface_get_sub_resource_idx(surface);
-    device = texture->resource.device;
+    if (rt && rt->resource->format->id != WINED3DFMT_NULL)
+    {
+        struct wined3d_texture *rt_texture;
+        unsigned int rt_level;
 
 
-    format = texture->resource.format;
-    if (!format->ddi_format)
+        if (rt->resource->type == WINED3D_RTYPE_BUFFER)
+        {
+            FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
+            return;
+        }
+        rt_texture = wined3d_texture_from_resource(rt->resource);
+        rt_level = rt->sub_resource_idx % rt_texture->level_count;
+
+        width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
+        height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
+    }
+    else
     {
     {
-        WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
-        return;
+        width = wined3d_texture_get_level_pow2_width(texture, level);
+        height = wined3d_texture_get_level_pow2_height(texture, level);
     }
 
     }
 
-    if (device->d3d_initialized)
-        context = context_acquire(device, NULL, 0);
-
-    wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
-    wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
-    desc.pMemory = context_map_bo_address(context, &data,
-            texture->sub_resources[sub_resource_idx].size,
-            GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
+    src_width = wined3d_texture_get_level_pow2_width(texture, level);
+    src_height = wined3d_texture_get_level_pow2_height(texture, level);
 
 
-    if (context)
-        context_release(context);
-
-    desc.Format = format->ddi_format;
-    desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level);
-    desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level);
-    desc.Pitch = row_pitch;
-    desc.hDeviceDc = CreateCompatibleDC(NULL);
-    desc.pColorTable = NULL;
+    /* A depth stencil smaller than the render target is not valid */
+    if (width > src_width || height > src_height)
+        return;
 
 
-    status = D3DKMTCreateDCFromMemory(&desc);
-    DeleteDC(desc.hDeviceDc);
-    if (status)
+    /* Remove any renderbuffer set if the sizes match */
+    if (width == src_width && height == src_height)
     {
     {
-        WARN("Failed to create DC, status %#x.\n", status);
+        texture->current_renderbuffer = NULL;
         return;
     }
 
         return;
     }
 
-    surface->dc = desc.hDc;
-    surface->bitmap = desc.hBitmap;
-
-    TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface);
-}
-
-static void texture2d_destroy_dc(void *object)
-{
-    struct wined3d_surface *surface = object;
-    D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
-    struct wined3d_context *context = NULL;
-    struct wined3d_texture *texture;
-    struct wined3d_bo_address data;
-    unsigned int sub_resource_idx;
-    struct wined3d_device *device;
-    NTSTATUS status;
-
-    texture = surface->container;
-    sub_resource_idx = surface_get_sub_resource_idx(surface);
-    device = texture->resource.device;
-
-    if (!surface->dc)
+    /* Look if we've already got a renderbuffer of the correct dimensions */
+    LIST_FOR_EACH_ENTRY(entry, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
     {
     {
-        ERR("Surface %p has no DC.\n", surface);
-        return;
+        if (entry->width == width && entry->height == height)
+        {
+            renderbuffer = entry->id;
+            texture->current_renderbuffer = entry;
+            break;
+        }
     }
 
     }
 
-    TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap);
-
-    destroy_desc.hDc = surface->dc;
-    destroy_desc.hBitmap = surface->bitmap;
-    if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
-        ERR("Failed to destroy dc, status %#x.\n", status);
-    surface->dc = NULL;
-    surface->bitmap = NULL;
+    if (!renderbuffer)
+    {
+        gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
+                texture->resource.format->glInternal, width, height);
 
 
-    if (device->d3d_initialized)
-        context = context_acquire(device, NULL, 0);
+        entry = heap_alloc(sizeof(*entry));
+        entry->width = width;
+        entry->height = height;
+        entry->id = renderbuffer;
+        list_add_head(&texture->renderbuffers, &entry->entry);
 
 
-    wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
-    context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
+        texture->current_renderbuffer = entry;
+    }
 
 
-    if (context)
-        context_release(context);
+    checkGLcall("set_compatible_renderbuffer");
 }
 
 HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height,
 }
 
 HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height,
@@ -1362,7 +1540,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id, texture->resource.usage);
     UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1);
     struct wined3d_texture_sub_resource *sub_resource;
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id, texture->resource.usage);
     UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1);
     struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_surface *surface;
     DWORD valid_location = 0;
     BOOL create_dib = FALSE;
 
     DWORD valid_location = 0;
     BOOL create_dib = FALSE;
 
@@ -1385,12 +1562,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (texture->resource.type == WINED3D_RTYPE_TEXTURE_1D)
-    {
-        FIXME("Not yet supported for 1D textures.\n");
-        return WINED3DERR_INVALIDCALL;
-    }
-
     if (texture->resource.map_count)
     {
         WARN("Texture is mapped.\n");
     if (texture->resource.map_count)
     {
         WARN("Texture is mapped.\n");
@@ -1415,10 +1586,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     wined3d_resource_wait_idle(&texture->resource);
 
     sub_resource = &texture->sub_resources[0];
     wined3d_resource_wait_idle(&texture->resource);
 
     sub_resource = &texture->sub_resources[0];
-    surface = sub_resource->u.surface;
-    if (surface->dc)
+    if (texture->dc_info && texture->dc_info[0].dc)
     {
     {
-        wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface);
+        struct wined3d_texture_idx texture_idx = {texture, 0};
+
+        wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx);
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
         create_dib = TRUE;
     }
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
         create_dib = TRUE;
     }
@@ -1446,7 +1618,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     else
         texture->target = GL_TEXTURE_2D;
 
     else
         texture->target = GL_TEXTURE_2D;
 
-    if ((!is_power_of_two(width) || !is_power_of_two(height)) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]
+    if (((width & (width - 1)) || (height & (height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]
             && !gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
     {
         texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED;
             && !gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
     {
         texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED;
@@ -1486,7 +1658,9 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     if (create_dib)
     {
 
     if (create_dib)
     {
-        wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
+        struct wined3d_texture_idx texture_idx = {texture, 0};
+
+        wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
     }
 
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
     }
 
@@ -1495,16 +1669,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
 /* Context activation is done by the caller. */
 static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture,
 
 /* Context activation is done by the caller. */
 static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture,
-#if !defined(STAGING_CSMT)
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
-#else  /* STAGING_CSMT */
-        unsigned int sub_resource_idx, struct wined3d_context *context)
-#endif /* STAGING_CSMT */
 {
     struct wined3d_texture_sub_resource *sub_resource;
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
 {
     struct wined3d_texture_sub_resource *sub_resource;
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
-#if !defined(STAGING_CSMT)
     if (sub_resource->buffer_object)
         return;
 
     if (sub_resource->buffer_object)
         return;
 
@@ -1516,16 +1685,6 @@ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *textur
 
     TRACE("Created buffer object %u for texture %p, sub-resource %u.\n",
             sub_resource->buffer_object, texture, sub_resource_idx);
 
     TRACE("Created buffer object %u for texture %p, sub-resource %u.\n",
             sub_resource->buffer_object, texture, sub_resource_idx);
-#else  /* STAGING_CSMT */
-    if (sub_resource->buffer)
-        return;
-
-    sub_resource->buffer = wined3d_device_get_bo(texture->resource.device,
-            sub_resource->size, GL_STREAM_DRAW, GL_PIXEL_UNPACK_BUFFER, context);
-
-    TRACE("Created buffer object %u for texture %p, sub-resource %u.\n",
-            sub_resource->buffer->name, texture, sub_resource_idx);
-#endif /* STAGING_CSMT */
 }
 
 static void wined3d_texture_force_reload(struct wined3d_texture *texture)
 }
 
 static void wined3d_texture_force_reload(struct wined3d_texture *texture)
@@ -1543,10 +1702,17 @@ static void wined3d_texture_force_reload(struct wined3d_texture *texture)
     }
 }
 
     }
 }
 
+/* Context activation is done by the caller. */
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
 {
     DWORD alloc_flag = srgb ? WINED3D_TEXTURE_SRGB_ALLOCATED : WINED3D_TEXTURE_RGB_ALLOCATED;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
 {
     DWORD alloc_flag = srgb ? WINED3D_TEXTURE_SRGB_ALLOCATED : WINED3D_TEXTURE_RGB_ALLOCATED;
+    const struct wined3d_format *format = texture->resource.format;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_color_key_conversion *conversion;
+    GLenum internal;
+
+    TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id));
 
     if (!d3d_info->shader_color_key
             && !(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
 
     if (!d3d_info->shader_color_key
             && !(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
@@ -1561,7 +1727,36 @@ void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct win
     if (texture->flags & alloc_flag)
         return;
 
     if (texture->flags & alloc_flag)
         return;
 
-    texture->texture_ops->texture_prepare_texture(texture, context, srgb);
+    if (format->conv_byte_count)
+    {
+        texture->flags |= WINED3D_TEXTURE_CONVERTED;
+    }
+    else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
+    {
+        texture->flags |= WINED3D_TEXTURE_CONVERTED;
+        format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage);
+        TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format->id));
+    }
+
+    wined3d_texture_bind_and_dirtify(texture, context, srgb);
+
+    if (srgb)
+        internal = format->glGammaInternal;
+    else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
+            && wined3d_resource_is_offscreen(&texture->resource))
+        internal = format->rtInternal;
+    else
+        internal = format->glInternal;
+
+    if (!internal)
+        FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id));
+
+    TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType);
+
+    if (wined3d_texture_use_immutable_storage(texture, gl_info))
+        wined3d_texture_allocate_gl_immutable_storage(texture, internal, gl_info);
+    else
+        wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info);
     texture->flags |= alloc_flag;
 }
 
     texture->flags |= alloc_flag;
 }
 
@@ -1612,10 +1807,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
                 return TRUE;
 
             if (!wined3d_resource_allocate_sysmem(&texture->resource))
                 return TRUE;
 
             if (!wined3d_resource_allocate_sysmem(&texture->resource))
-            {
-                ERR("Failed to allocate system memory.\n");
                 return FALSE;
                 return FALSE;
-            }
             return TRUE;
 
         case WINED3D_LOCATION_USER_MEMORY:
             return TRUE;
 
         case WINED3D_LOCATION_USER_MEMORY:
@@ -1624,11 +1816,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
             return TRUE;
 
         case WINED3D_LOCATION_BUFFER:
             return TRUE;
 
         case WINED3D_LOCATION_BUFFER:
-#if !defined(STAGING_CSMT)
             wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context->gl_info);
             wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context->gl_info);
-#else  /* STAGING_CSMT */
-            wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context);
-#endif /* STAGING_CSMT */
             return TRUE;
 
         case WINED3D_LOCATION_TEXTURE_RGB:
             return TRUE;
 
         case WINED3D_LOCATION_TEXTURE_RGB:
@@ -1693,518 +1881,260 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
     return WINED3D_OK;
 }
 
     return WINED3D_OK;
 }
 
-void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_box *box,
-        const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch)
-{
-    texture->texture_ops->texture_upload_data(texture, sub_resource_idx,
-            context, box, data, row_pitch, slice_pitch);
-}
-
-
 /* This call just uploads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
 /* This call just uploads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
-static void texture1d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_box *box, const struct wined3d_const_bo_address *data,
-        unsigned int row_pitch, unsigned int slice_pitch)
+void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box,
+        const struct wined3d_const_bo_address *data, unsigned int src_row_pitch, unsigned int src_slice_pitch,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb)
 {
 {
-    struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface;
-    const struct wined3d_format *format = texture->resource.format;
-    unsigned int level = sub_resource_idx % texture->level_count;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    const void *mem = data->addr;
+    unsigned int update_w = src_box->right - src_box->left;
+    unsigned int update_h = src_box->bottom - src_box->top;
+    unsigned int update_d = src_box->back - src_box->front;
+    struct wined3d_bo_address bo;
     void *converted_mem = NULL;
     void *converted_mem = NULL;
-    unsigned int width, x, update_w;
+    struct wined3d_format f;
+    unsigned int level;
     GLenum target;
 
     GLenum target;
 
-    TRACE("texture %p, sub_resource_idx %u, context %p, box %p, data {%#x:%p}, row_pitch %#x, slice_pitch %#x.\n",
-            texture, sub_resource_idx, context, box, data->buffer_object, data->addr, row_pitch, slice_pitch);
-
-    width = wined3d_texture_get_level_width(texture, level);
+    TRACE("texture %p, sub_resource_idx %u, context %p, format %s, src_box %s, data {%#x:%p}, "
+            "src_row_pitch %#x, src_slice_pitch %#x, dst_x %u, dst_y %u, dst_z %u, srgb %#x.\n",
+            texture, sub_resource_idx, context, debug_d3dformat(format->id), debug_box(src_box),
+            data->buffer_object, data->addr, src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, srgb);
 
 
-    if (!box)
-    {
-        x = 0;
-        update_w = width;
-    }
-    else
+    if (texture->sub_resources[sub_resource_idx].map_count)
     {
     {
-        x = box->left;
-        update_w = box->right - box->left;
+        WARN("Uploading a texture that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n");
+        texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM;
     }
 
     }
 
-    if (format->upload)
+    if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_HEIGHT_SCALE)
     {
     {
-        unsigned int dst_row_pitch;
-
-        if (data->buffer_object)
-            ERR("Loading a converted texture from a PBO.\n");
-        if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
-            ERR("Converting a block-based format.\n");
-
-        dst_row_pitch = update_w * format->conv_byte_count;
-
-        converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_row_pitch);
-        format->upload(data->addr, converted_mem, row_pitch, slice_pitch, dst_row_pitch, dst_row_pitch, update_w, 1, 1);
-        mem = converted_mem;
+        update_h *= format->height_scale.numerator;
+        update_h /= format->height_scale.denominator;
     }
 
     }
 
-    if (data->buffer_object)
+    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
+    level = sub_resource_idx % texture->level_count;
+
+    switch (target)
     {
     {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object));
-        checkGLcall("glBindBuffer");
+        case GL_TEXTURE_1D_ARRAY:
+            dst_y = sub_resource_idx / texture->level_count;
+            update_h = 1;
+            break;
+        case GL_TEXTURE_2D_ARRAY:
+            dst_z = sub_resource_idx / texture->level_count;
+            update_d = 1;
+            break;
+        case GL_TEXTURE_2D_MULTISAMPLE:
+        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+            FIXME("Not supported for multisample textures.\n");
+            return;
     }
 
     }
 
-    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
-    if (target == GL_TEXTURE_1D_ARRAY)
+    bo.buffer_object = data->buffer_object;
+    bo.addr = (BYTE *)data->addr + src_box->front * src_slice_pitch;
+    if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
     {
     {
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, row_pitch / format->byte_count);
-
-        gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, x, surface->texture_layer, update_w, 1, format->glFormat, format->glType, mem);
-        checkGLcall("glTexSubImage2D");
-
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        bo.addr += (src_box->top / format->block_height) * src_row_pitch;
+        bo.addr += (src_box->left / format->block_width) * format->block_byte_count;
     }
     else
     {
     }
     else
     {
-        gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, x, update_w, format->glFormat, format->glType, mem);
-        checkGLcall("glTexSubImage1D");
+        bo.addr += src_box->top * src_row_pitch;
+        bo.addr += src_box->left * format->byte_count;
     }
 
     }
 
-    if (data->buffer_object)
+    if (format->upload)
     {
     {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
-        checkGLcall("glBindBuffer");
-    }
-
-    HeapFree(GetProcessHeap(), 0, converted_mem);
-}
+        unsigned int dst_row_pitch, dst_slice_pitch;
+        void *src_mem;
 
 
-/* Context activation is done by the caller. */
-static void texture1d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_bo_address *data)
-{
-    struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface;
-    const struct wined3d_format *format = texture->resource.format;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_texture_sub_resource *sub_resource;
-    BYTE *temporary_mem = NULL;
-    void *mem;
-    GLenum target;
+        if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+            ERR("Converting a block-based format.\n");
 
 
-    sub_resource = &texture->sub_resources[sub_resource_idx];
+        f = *format;
+        f.byte_count = format->conv_byte_count;
+        format = &f;
 
 
-    if (format->conv_byte_count)
-    {
-        FIXME("Attempting to download a converted 1d texture, format %s.\n",
-                debug_d3dformat(format->id));
-        return;
-    }
+        wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch);
 
 
-    target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
-    if (target == GL_TEXTURE_1D_ARRAY)
-    {
-         WARN_(d3d_perf)("Downloading all miplevel layers to get the surface data for a single sub-resource.\n");
-
-        if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size)))
+        if (!(converted_mem = heap_calloc(update_d, dst_slice_pitch)))
         {
         {
-            ERR("Out of memory.\n");
+            ERR("Failed to allocate upload buffer.\n");
             return;
         }
 
             return;
         }
 
-        mem = temporary_mem;
-    }
-    else if (data->buffer_object)
-    {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object));
-        checkGLcall("glBindBuffer");
-        mem = data->addr;
-    }
-    else
-        mem = data->addr;
-
-    gl_info->gl_ops.gl.p_glGetTexImage(target, sub_resource_idx,
-            format->glFormat, format->glType, mem);
-    checkGLcall("glGetTexImage");
+        src_mem = context_map_bo_address(context, &bo, src_slice_pitch,
+                GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
+        format->upload(src_mem, converted_mem, src_row_pitch, src_slice_pitch,
+                dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d);
+        context_unmap_bo_address(context, &bo, GL_PIXEL_UNPACK_BUFFER);
 
 
-    if (temporary_mem)
-    {
-        void *src_data = temporary_mem + surface->texture_layer * sub_resource->size;
-        if (data->buffer_object)
-        {
-            GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object));
-            checkGLcall("glBindBuffer");
-            GL_EXTCALL(glBufferSubData(GL_PIXEL_PACK_BUFFER, 0, sub_resource->size, src_data));
-            checkGLcall("glBufferSubData");
-        }
-        else
-        {
-            memcpy(data->addr, src_data, sub_resource->size);
-        }
+        bo.buffer_object = 0;
+        bo.addr = converted_mem;
+        src_row_pitch = dst_row_pitch;
+        src_slice_pitch = dst_slice_pitch;
     }
 
     }
 
-    if (data->buffer_object)
+    if (bo.buffer_object)
     {
     {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
+        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bo.buffer_object));
         checkGLcall("glBindBuffer");
     }
 
         checkGLcall("glBindBuffer");
     }
 
-    HeapFree(GetProcessHeap(), 0, temporary_mem);
-}
-
-/* Context activation is done by the caller. */
-static void texture1d_srgb_transfer(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        struct wined3d_context *context, BOOL dest_is_srgb)
-{
-    struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
-    unsigned int row_pitch, slice_pitch;
-    struct wined3d_bo_address data;
-
-    WARN_(d3d_perf)("Performing slow rgb/srgb 1d texture transfer.\n");
-    data.buffer_object = 0;
-    if (!(data.addr = HeapAlloc(GetProcessHeap(), 0, sub_resource->size)))
-        return;
-
-    wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
-    wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb);
-    texture1d_download_data(texture, sub_resource_idx, context, &data);
-    wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb);
-    texture1d_upload_data(texture, sub_resource_idx, context, NULL,
-            wined3d_const_bo_address(&data), row_pitch, slice_pitch);
-
-    HeapFree(GetProcessHeap(), 0, data.addr);
-}
-
-/* Context activation is done by the caller. */
-static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        struct wined3d_context *context, DWORD location)
-{
-    struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
-    DWORD required_access = wined3d_resource_access_from_location(location);
-    unsigned int row_pitch, slice_pitch;
-
-    TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
-            texture, sub_resource_idx, context, wined3d_debug_location(location));
-
-    TRACE("Current resource location %s.\n", wined3d_debug_location(sub_resource->locations));
-
-    if ((sub_resource->locations & location) == location)
-    {
-        TRACE("Location(s) already up to date.\n");
-        return TRUE;
-    }
-
-    if ((texture->resource.access & required_access) != required_access)
+    if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
     {
     {
-        ERR("Operation requires %#x access, but 1d texture only has %#x.\n",
-                required_access, texture->resource.access);
-        return FALSE;
-    }
+        unsigned int dst_row_pitch, dst_slice_pitch;
+        const BYTE *addr = bo.addr;
+        GLenum internal;
 
 
-    if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location))
-        return FALSE;
+        if (srgb)
+            internal = format->glGammaInternal;
+        else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
+                && wined3d_resource_is_offscreen(&texture->resource))
+            internal = format->rtInternal;
+        else
+            internal = format->glInternal;
 
 
-    if (sub_resource->locations & WINED3D_LOCATION_DISCARDED)
-    {
-        TRACE("1d texture previously discarded, nothing to do.\n");
-        wined3d_texture_validate_location(texture, sub_resource_idx, location);
-        wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_DISCARDED);
-        goto done;
-    }
+        wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch);
 
 
-    switch (location)
-    {
-        case WINED3D_LOCATION_TEXTURE_RGB:
-        case WINED3D_LOCATION_TEXTURE_SRGB:
-            if (sub_resource->locations & WINED3D_LOCATION_SYSMEM)
-            {
-                struct wined3d_const_bo_address data = {0, texture->resource.heap_memory};
-                data.addr += sub_resource->offset;
-                wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB);
-                wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
-                texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch);
-            }
-            else if (sub_resource->locations & WINED3D_LOCATION_BUFFER)
-            {
-#if !defined(STAGING_CSMT)
-                struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL};
-#else  /* STAGING_CSMT */
-                struct wined3d_const_bo_address data = {sub_resource->buffer->name, NULL};
-#endif /* STAGING_CSMT */
-                wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB);
-                wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
-                texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch);
-            }
-            else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
-            {
-                texture1d_srgb_transfer(texture, sub_resource_idx, context, TRUE);
-            }
-            else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_SRGB)
-            {
-                texture1d_srgb_transfer(texture, sub_resource_idx, context, FALSE);
-            }
-            else
-            {
-                FIXME("Implement 1d texture loading from %s.\n", wined3d_debug_location(sub_resource->locations));
-                return FALSE;
-            }
-            break;
+        TRACE("Uploading compressed data, target %#x, level %u, x %u, y %u, z %u, "
+                "w %u, h %u, d %u, format %#x, image_size %#x, addr %p.\n",
+                target, level, dst_x, dst_y, dst_z, update_w, update_h,
+                update_d, internal, dst_slice_pitch, addr);
 
 
-        case WINED3D_LOCATION_SYSMEM:
-            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+        if (target == GL_TEXTURE_1D)
+        {
+            GL_EXTCALL(glCompressedTexSubImage1D(target, level, dst_x,
+                    update_w, internal, dst_row_pitch, addr));
+        }
+        else if (dst_row_pitch == src_row_pitch)
+        {
+            if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D)
             {
             {
-                struct wined3d_bo_address data = {0, texture->resource.heap_memory};
-
-                data.addr += sub_resource->offset;
-                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
-                    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
-                else
-                    wined3d_texture_bind_and_dirtify(texture, context, TRUE);
-
-                texture1d_download_data(texture, sub_resource_idx, context, &data);
-                ++texture->download_count;
+                GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, dst_y, dst_z,
+                        update_w, update_h, update_d, internal, dst_slice_pitch * update_d, addr));
             }
             else
             {
             }
             else
             {
-                FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n",
-                        wined3d_debug_location(sub_resource->locations));
-                return FALSE;
+                GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, dst_y,
+                        update_w, update_h, internal, dst_slice_pitch, addr));
             }
             }
-            break;
-
-        case WINED3D_LOCATION_BUFFER:
-            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
-            {
-#if !defined(STAGING_CSMT)
-                struct wined3d_bo_address data = {sub_resource->buffer_object, NULL};
-#else  /* STAGING_CSMT */
-                struct wined3d_bo_address data = {sub_resource->buffer->name, NULL};
-#endif /* STAGING_CSMT */
-
-                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
-                    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
-                else
-                    wined3d_texture_bind_and_dirtify(texture, context, TRUE);
+        }
+        else
+        {
+            unsigned int row_count = (update_h + format->block_height - 1) / format->block_height;
+            unsigned int row, y, z;
 
 
-                texture1d_download_data(texture, sub_resource_idx, context, &data);
-            }
-            else
+            /* glCompressedTexSubImage2D() ignores pixel store state, so we
+             * can't use the unpack row length like for glTexSubImage2D. */
+            for (z = dst_z; z < dst_z + update_d; ++z)
             {
             {
-                FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n",
-                        wined3d_debug_location(sub_resource->locations));
-                return FALSE;
+                for (row = 0, y = dst_y; row < row_count; ++row)
+                {
+                    if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D)
+                    {
+                        GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, y, z,
+                                update_w, format->block_height, 1, internal, dst_row_pitch, addr));
+                    }
+                    else
+                    {
+                        GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, y,
+                                update_w, format->block_height, internal, dst_row_pitch, addr));
+                    }
+
+                    y += format->block_height;
+                    addr += src_row_pitch;
+                }
             }
             }
-            break;
-
-        default:
-            FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location),
-                    wined3d_debug_location(sub_resource->locations));
-            return FALSE;
+        }
+        checkGLcall("Upload compressed texture data");
     }
     }
-
-done:
-    wined3d_texture_validate_location(texture, sub_resource_idx, location);
-
-    return TRUE;
-}
-
-static void texture1d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
-{
-    const struct wined3d_format *format = texture->resource.format;
-    unsigned int sub_count = texture->level_count * texture->layer_count;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    unsigned int width;
-    GLenum internal;
-
-    wined3d_texture_bind_and_dirtify(texture, context, srgb);
-
-    if (srgb)
-        internal = format->glGammaInternal;
-    else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
-            && wined3d_resource_is_offscreen(&texture->resource))
-        internal = format->rtInternal;
     else
     else
-        internal = format->glInternal;
-
-    if (wined3d_texture_use_immutable_storage(texture, gl_info))
     {
     {
-        width = wined3d_texture_get_level_width(texture, 0);
+        TRACE("Uploading data, target %#x, level %u, x %u, y %u, z %u, "
+                "w %u, h %u, d %u, format %#x, type %#x, addr %p.\n",
+                target, level, dst_x, dst_y, dst_z, update_w, update_h,
+                update_d, format->glFormat, format->glType, bo.addr);
 
 
-        if (texture->target == GL_TEXTURE_1D_ARRAY)
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_row_pitch / format->byte_count);
+        if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D)
         {
         {
-            GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count, internal, width, texture->layer_count));
-            checkGLcall("glTexStorage2D");
+            GL_EXTCALL(glTexSubImage3D(target, level, dst_x, dst_y, dst_z,
+                    update_w, update_h, update_d, format->glFormat, format->glType, bo.addr));
         }
         }
-        else
+        else if (target == GL_TEXTURE_1D)
         {
         {
-            GL_EXTCALL(glTexStorage1D(texture->target, texture->level_count, internal, width));
-            checkGLcall("glTexStorage1D");
+            gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, dst_x,
+                    update_w, format->glFormat, format->glType, bo.addr);
         }
         }
-    }
-    else
-    {
-        unsigned int i;
-
-        for (i = 0; i < sub_count; ++i)
+        else
         {
         {
-            GLenum target;
-            struct wined3d_surface *surface = texture->sub_resources[i].u.surface;
-            width = wined3d_texture_get_level_width(texture, surface->texture_level);
-            target = wined3d_texture_get_sub_resource_target(texture, i);
-
-            if (texture->target == GL_TEXTURE_1D_ARRAY)
-            {
-                gl_info->gl_ops.gl.p_glTexImage2D(target, surface->texture_level,
-                        internal, width, texture->layer_count, 0, format->glFormat, format->glType, NULL);
-                checkGLcall("glTexImage2D");
-            }
-            else
-            {
-                gl_info->gl_ops.gl.p_glTexImage1D(target, surface->texture_level,
-                        internal, width, 0, format->glFormat, format->glType, NULL);
-                checkGLcall("glTexImage1D");
-            }
+            gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_x, dst_y,
+                    update_w, update_h, format->glFormat, format->glType, bo.addr);
         }
         }
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        checkGLcall("Upload texture data");
     }
     }
-}
-
-static void texture1d_cleanup_sub_resources(struct wined3d_texture *texture)
-{
-}
 
 
-static const struct wined3d_texture_ops texture1d_ops =
-{
-    texture1d_upload_data,
-    texture1d_load_location,
-    texture1d_prepare_texture,
-    texture1d_cleanup_sub_resources,
-};
-
-static void texture2d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_box *box,
-        const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch)
-{
-    unsigned int texture_level;
-    POINT dst_point;
-    RECT src_rect;
-
-    src_rect.left = 0;
-    src_rect.top = 0;
-    if (box)
+    if (bo.buffer_object)
     {
     {
-        dst_point.x = box->left;
-        dst_point.y = box->top;
-        src_rect.right = box->right - box->left;
-        src_rect.bottom = box->bottom - box->top;
-    }
-    else
-    {
-        dst_point.x = dst_point.y = 0;
-        texture_level = sub_resource_idx % texture->level_count;
-        src_rect.right = wined3d_texture_get_level_width(texture, texture_level);
-        src_rect.bottom = wined3d_texture_get_level_height(texture, texture_level);
+        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
+        checkGLcall("glBindBuffer");
     }
     }
+    heap_free(converted_mem);
 
 
-    wined3d_surface_upload_data(texture->sub_resources[sub_resource_idx].u.surface, context->gl_info,
-            texture->resource.format, &src_rect, row_pitch, &dst_point, FALSE, data);
-}
-
-static BOOL texture2d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        struct wined3d_context *context, DWORD location)
-{
-    return surface_load_location(texture->sub_resources[sub_resource_idx].u.surface, context, location);
-}
-
-/* Context activation is done by the caller. */
-static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
-{
-    const struct wined3d_format *format = texture->resource.format;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    const struct wined3d_color_key_conversion *conversion;
-    GLenum internal;
-
-    TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id));
-
-    if (format->conv_byte_count)
-    {
-        texture->flags |= WINED3D_TEXTURE_CONVERTED;
-    }
-    else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE)))
+    if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE)
     {
     {
-        texture->flags |= WINED3D_TEXTURE_CONVERTED;
-        format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage);
-        TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format->id));
-    }
-
-    wined3d_texture_bind_and_dirtify(texture, context, srgb);
-
-    if (srgb)
-        internal = format->glGammaInternal;
-    else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET
-            && wined3d_resource_is_offscreen(&texture->resource))
-        internal = format->rtInternal;
-    else
-        internal = format->glInternal;
-
-    if (!internal)
-        FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id));
-
-    TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType);
+        struct wined3d_device *device = texture->resource.device;
+        unsigned int i;
 
 
-    if (wined3d_texture_use_immutable_storage(texture, gl_info))
-        wined3d_texture_allocate_gl_immutable_storage(texture, internal, gl_info);
-    else
-        wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info);
+        for (i = 0; i < device->context_count; ++i)
+        {
+            context_texture_update(device->contexts[i], texture);
+        }
+    }
 }
 
 }
 
-static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
+/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */
+static BOOL texture2d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD location)
 {
 {
-    unsigned int sub_count = texture->level_count * texture->layer_count;
-    struct wined3d_device *device = texture->resource.device;
-    struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_renderbuffer_entry *entry, *entry2;
-    const struct wined3d_gl_info *gl_info = NULL;
-    struct wined3d_context *context = NULL;
-    struct wined3d_surface *surface;
-    unsigned int i;
+    TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
+            texture, sub_resource_idx, context, wined3d_debug_location(location));
 
 
-    for (i = 0; i < sub_count; ++i)
+    switch (location)
     {
     {
-        sub_resource = &texture->sub_resources[i];
-        if (!(surface = sub_resource->u.surface))
-            continue;
+        case WINED3D_LOCATION_USER_MEMORY:
+        case WINED3D_LOCATION_SYSMEM:
+        case WINED3D_LOCATION_BUFFER:
+            return texture2d_load_sysmem(texture, sub_resource_idx, context, location);
 
 
-        TRACE("surface %p.\n", surface);
+        case WINED3D_LOCATION_DRAWABLE:
+            return texture2d_load_drawable(texture, sub_resource_idx, context);
 
 
-        if (!context && !list_empty(&surface->renderbuffers))
-        {
-            context = context_acquire(device, NULL, 0);
-            gl_info = context->gl_info;
-        }
+        case WINED3D_LOCATION_RB_RESOLVED:
+        case WINED3D_LOCATION_RB_MULTISAMPLE:
+            return texture2d_load_renderbuffer(texture, sub_resource_idx, context, location);
 
 
-        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-        {
-            TRACE("Deleting renderbuffer %u.\n", entry->id);
-            context_gl_resource_released(device, entry->id, TRUE);
-            gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
-            heap_free(entry);
-        }
+        case WINED3D_LOCATION_TEXTURE_RGB:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+            return texture2d_load_texture(texture, sub_resource_idx, context,
+                    location == WINED3D_LOCATION_TEXTURE_SRGB);
 
 
-        if (surface->dc)
-            texture2d_destroy_dc(surface);
+        default:
+            ERR("Don't know how to handle location %#x.\n", location);
+            return FALSE;
     }
     }
-    if (context)
-        context_release(context);
-    heap_free(texture->sub_resources[0].u.surface);
 }
 
 static const struct wined3d_texture_ops texture2d_ops =
 {
 }
 
 static const struct wined3d_texture_ops texture2d_ops =
 {
-    texture2d_upload_data,
     texture2d_load_location,
     texture2d_load_location,
-    texture2d_prepare_texture,
-    texture2d_cleanup_sub_resources,
 };
 
 struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource)
 };
 
 struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource)
@@ -2236,6 +2166,7 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
 {
     struct wined3d_texture *texture = texture_from_resource(resource);
     UINT sub_count = texture->level_count * texture->layer_count;
 {
     struct wined3d_texture *texture = texture_from_resource(resource);
     UINT sub_count = texture->level_count * texture->layer_count;
+    struct wined3d_renderbuffer_entry *entry, *entry2;
     struct wined3d_device *device = resource->device;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
     struct wined3d_device *device = resource->device;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
@@ -2268,30 +2199,19 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
             wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_DISCARDED);
         }
 
             wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_DISCARDED);
         }
 
-#if !defined(STAGING_CSMT)
         if (sub_resource->buffer_object)
             wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
         if (sub_resource->buffer_object)
             wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
-#else  /* STAGING_CSMT */
-        if (sub_resource->buffer)
-            wined3d_texture_remove_buffer_object(texture, i, context);
-#endif /* STAGING_CSMT */
-
-        if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
-        {
-            struct wined3d_surface *surface = sub_resource->u.surface;
-            struct wined3d_renderbuffer_entry *entry, *entry2;
+    }
 
 
-            LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-            {
-                context_gl_resource_released(device, entry->id, TRUE);
-                gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
-                list_remove(&entry->entry);
-                heap_free(entry);
-            }
-            list_init(&surface->renderbuffers);
-            surface->current_renderbuffer = NULL;
-        }
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        context_gl_resource_released(device, entry->id, TRUE);
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+        list_remove(&entry->entry);
+        heap_free(entry);
     }
     }
+    list_init(&texture->renderbuffers);
+    texture->current_renderbuffer = NULL;
 
     context_release(context);
 
 
     context_release(context);
 
@@ -2515,140 +2435,179 @@ static const struct wined3d_resource_ops texture_resource_ops =
     texture_resource_sub_resource_unmap,
 };
 
     texture_resource_sub_resource_unmap,
 };
 
-static HRESULT texture1d_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
-        UINT layer_count, UINT level_count, struct wined3d_device *device, void *parent,
-        const struct wined3d_parent_ops *parent_ops)
+/* Context activation is done by the caller. */
+static void texture1d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        const struct wined3d_context *context, const struct wined3d_bo_address *data)
 {
 {
-    struct wined3d_device_parent *device_parent = device->device_parent;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    struct wined3d_surface *surfaces;
-    unsigned int i, j;
-    HRESULT hr;
+    const struct wined3d_format *format = texture->resource.format;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
 
 
-    if (layer_count > 1 && !gl_info->supported[EXT_TEXTURE_ARRAY])
+    if (format->conv_byte_count)
     {
     {
-        WARN("OpenGL implementation does not support array textures.\n");
-        return WINED3DERR_INVALIDCALL;
+        FIXME("Attempting to download a converted texture, format %s.\n",
+                debug_d3dformat(format->id));
+        return;
     }
 
     }
 
-    /* TODO: It should only be possible to create textures for formats
-     * that are reported as supported. */
-    if (WINED3DFMT_UNKNOWN >= desc->format)
+    if (data->buffer_object)
     {
     {
-        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
-        return WINED3DERR_INVALIDCALL;
+        GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object));
+        checkGLcall("glBindBuffer");
     }
 
     }
 
-    if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP)
-    {
-        WARN("1d textures can not be used for cube mapping, returning D3DERR_INVALIDCALL.\n");
-        return WINED3DERR_INVALIDCALL;
-    }
+    gl_info->gl_ops.gl.p_glGetTexImage(texture->target, sub_resource_idx,
+            format->glFormat, format->glType, data->addr);
+    checkGLcall("glGetTexImage");
 
 
-    if ((desc->usage & WINED3DUSAGE_DYNAMIC && wined3d_resource_access_is_managed(desc->access))
-            || (desc->usage & WINED3DUSAGE_SCRATCH))
+    if (data->buffer_object)
     {
     {
-        WARN("Attempted to create a DYNAMIC texture in pool %s.\n", wined3d_debug_resource_access(desc->access));
-        return WINED3DERR_INVALIDCALL;
+        GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
+        checkGLcall("glBindBuffer");
     }
     }
+}
 
 
-    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && !is_power_of_two(desc->width))
-    {
-        if (desc->usage & WINED3DUSAGE_SCRATCH)
-        {
-            WARN("Creating a scratch NPOT 1d texture despite lack of HW support.\n");
-        }
-        else
-        {
-            WARN("Attempted to create a NPOT 1d texture (%u, %u, %u) without GL support.\n",
-                    desc->width, desc->height, desc->depth);
-            return WINED3DERR_INVALIDCALL;
-        }
-    }
+/* Context activation is done by the caller. */
+static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD location)
+{
+    struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
+    unsigned int row_pitch, slice_pitch;
 
 
-    if (desc->usage & WINED3DUSAGE_QUERY_GENMIPMAP)
-    {
-        if (level_count != 1)
-        {
-            WARN("WINED3DUSAGE_QUERY_GENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n");
-            return WINED3DERR_INVALIDCALL;
-        }
-    }
+    TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
+            texture, sub_resource_idx, context, wined3d_debug_location(location));
+
+    if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location))
+        return FALSE;
 
 
-    if (FAILED(hr = wined3d_texture_init(texture, &texture1d_ops, layer_count, level_count, desc,
-            0, device, parent, parent_ops, &texture_resource_ops)))
+    switch (location)
     {
     {
-        WARN("Failed to initialize texture, returning %#x.\n", hr);
-        return hr;
-    }
+        case WINED3D_LOCATION_TEXTURE_RGB:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+            if (sub_resource->locations & WINED3D_LOCATION_SYSMEM)
+            {
+                struct wined3d_const_bo_address data = {0, texture->resource.heap_memory};
+                struct wined3d_box src_box;
 
 
-    texture->pow2_matrix[0] = 1.0f;
-    texture->pow2_matrix[5] = 1.0f;
-    texture->pow2_matrix[10] = 1.0f;
-    texture->pow2_matrix[15] = 1.0f;
-    texture->target = (layer_count > 1) ? GL_TEXTURE_1D_ARRAY : GL_TEXTURE_1D;
+                data.addr += sub_resource->offset;
+                wined3d_texture_bind_and_dirtify(texture, context,
+                        location == WINED3D_LOCATION_TEXTURE_SRGB);
+                wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
+                wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box);
+                wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format,
+                        &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE);
+            }
+            else if (sub_resource->locations & WINED3D_LOCATION_BUFFER)
+            {
+                struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL};
+                struct wined3d_box src_box;
 
 
-    if (wined3d_texture_use_pbo(texture, gl_info))
-    {
-        wined3d_resource_free_sysmem(&texture->resource);
-        texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
-    }
+                wined3d_texture_bind_and_dirtify(texture, context,
+                        location == WINED3D_LOCATION_TEXTURE_SRGB);
+                wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
+                wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box);
+                wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format,
+                        &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE);
+            }
+            else
+            {
+                FIXME("Implement texture loading from %s.\n", wined3d_debug_location(sub_resource->locations));
+                return FALSE;
+            }
+            break;
 
 
-    if (level_count > ~(SIZE_T)0 / layer_count
-            || !(surfaces = heap_calloc(level_count * layer_count, sizeof(*surfaces))))
-    {
-        wined3d_texture_cleanup_sync(texture);
-        return E_OUTOFMEMORY;
-    }
+        case WINED3D_LOCATION_SYSMEM:
+            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            {
+                struct wined3d_bo_address data = {0, texture->resource.heap_memory};
 
 
-    /* Generate all the surfaces. */
-    for (i = 0; i < texture->level_count; ++i)
-    {
-        for (j = 0; j < texture->layer_count; ++j)
-        {
-            struct wined3d_texture_sub_resource *sub_resource;
-            unsigned int idx = j * texture->level_count + i;
-            struct wined3d_surface *surface;
-
-            surface = &surfaces[idx];
-            surface->container = texture;
-            surface->texture_level = i;
-            surface->texture_layer = j;
-            list_init(&surface->renderbuffers);
-
-            sub_resource = &texture->sub_resources[idx];
-            sub_resource->locations = WINED3D_LOCATION_DISCARDED;
-            sub_resource->u.surface = surface;
-
-            if (FAILED(hr = device_parent->ops->surface_created(device_parent,
-                    texture, idx, &sub_resource->parent, &sub_resource->parent_ops)))
+                data.addr += sub_resource->offset;
+                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
+                else
+                    wined3d_texture_bind_and_dirtify(texture, context, TRUE);
+
+                texture1d_download_data(texture, sub_resource_idx, context, &data);
+                ++texture->download_count;
+            }
+            else
             {
             {
-                WARN("Failed to create texture1d parent, hr %#x.\n", hr);
-                sub_resource->parent = NULL;
-                wined3d_texture_cleanup_sync(texture);
-                return hr;
+                FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n",
+                        wined3d_debug_location(sub_resource->locations));
+                return FALSE;
             }
             }
+            break;
 
 
-            TRACE("parent %p, parent_ops %p.\n", parent, parent_ops);
+        case WINED3D_LOCATION_BUFFER:
+            if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            {
+                struct wined3d_bo_address data = {sub_resource->buffer_object, NULL};
 
 
-            TRACE("Created 1d texture surface level %u, layer %u @ %p.\n", i, j, surface);
-        }
+                if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                    wined3d_texture_bind_and_dirtify(texture, context, FALSE);
+                else
+                    wined3d_texture_bind_and_dirtify(texture, context, TRUE);
+
+                texture1d_download_data(texture, sub_resource_idx, context, &data);
+            }
+            else
+            {
+                FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n",
+                        wined3d_debug_location(sub_resource->locations));
+                return FALSE;
+            }
+            break;
+
+        default:
+            FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location),
+                    wined3d_debug_location(sub_resource->locations));
+            return FALSE;
     }
 
     }
 
-    return WINED3D_OK;
+    return TRUE;
 }
 
 }
 
-static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+static const struct wined3d_texture_ops texture1d_ops =
+{
+    texture1d_load_location,
+};
+
+static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
         unsigned int layer_count, unsigned int level_count, DWORD flags, struct wined3d_device *device,
         unsigned int layer_count, unsigned int level_count, DWORD flags, struct wined3d_device *device,
-        void *parent, const struct wined3d_parent_ops *parent_ops)
+        void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_texture_ops *texture_ops)
 {
     struct wined3d_device_parent *device_parent = device->device_parent;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
 {
     struct wined3d_device_parent *device_parent = device->device_parent;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    struct wined3d_surface *surfaces;
-    UINT pow2_width, pow2_height;
-    unsigned int i, j, sub_count;
+    unsigned int sub_count, i, j, size, offset = 0;
+    unsigned int pow2_width, pow2_height;
+    const struct wined3d_format *format;
     HRESULT hr;
 
     HRESULT hr;
 
+    TRACE("texture %p, resource_type %s, format %s, multisample_type %#x, multisample_quality %#x, "
+            "usage %s, access %s, width %u, height %u, depth %u, layer_count %u, level_count %u, "
+            "flags %#x, device %p, parent %p, parent_ops %p, texture_ops %p.\n",
+            texture, debug_d3dresourcetype(desc->resource_type), debug_d3dformat(desc->format),
+            desc->multisample_type, desc->multisample_quality, debug_d3dusage(desc->usage),
+            wined3d_debug_resource_access(desc->access), desc->width, desc->height, desc->depth,
+            layer_count, level_count, flags, device, parent, parent_ops, texture_ops);
+
+    if (!desc->width || !desc->height || !desc->depth)
+        return WINED3DERR_INVALIDCALL;
+
+    if (desc->resource_type == WINED3D_RTYPE_TEXTURE_3D)
+    {
+        if (layer_count != 1)
+        {
+            ERR("Invalid layer count for volume texture.\n");
+            return E_INVALIDARG;
+        }
+
+        if (!gl_info->supported[EXT_TEXTURE3D])
+        {
+            WARN("OpenGL implementation does not support 3D textures.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+    }
+
     if (!(desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) && layer_count > 1
             && !gl_info->supported[EXT_TEXTURE_ARRAY])
     {
     if (!(desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) && layer_count > 1
             && !gl_info->supported[EXT_TEXTURE_ARRAY])
     {
@@ -2660,12 +2619,18 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
      * that are reported as supported. */
     if (WINED3DFMT_UNKNOWN >= desc->format)
     {
      * that are reported as supported. */
     if (WINED3DFMT_UNKNOWN >= desc->format)
     {
-        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
+        WARN("Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (desc->usage & WINED3DUSAGE_DYNAMIC && (wined3d_resource_access_is_managed(desc->access)
+            || desc->usage & WINED3DUSAGE_SCRATCH))
+    {
+        WARN("Attempted to create a dynamic texture with access %s and usage %s.\n",
+                wined3d_debug_resource_access(desc->access), debug_d3dusage(desc->usage));
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (desc->usage & WINED3DUSAGE_DYNAMIC && wined3d_resource_access_is_managed(desc->access))
-        FIXME("Trying to create a managed texture with dynamic usage.\n");
     if (!(desc->usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))
             && (flags & WINED3D_TEXTURE_CREATE_MAPPABLE))
         WARN("Creating a mappable texture that doesn't specify dynamic usage.\n");
     if (!(desc->usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))
             && (flags & WINED3D_TEXTURE_CREATE_MAPPABLE))
         WARN("Creating a mappable texture that doesn't specify dynamic usage.\n");
@@ -2674,15 +2639,16 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
 
     pow2_width = desc->width;
     pow2_height = desc->height;
 
     pow2_width = desc->width;
     pow2_height = desc->height;
-    if (((desc->width & (desc->width - 1)) || (desc->height & (desc->height - 1)))
+    if (((desc->width & (desc->width - 1)) || (desc->height & (desc->height - 1)) || (desc->depth & (desc->depth - 1)))
             && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
     {
         /* level_count == 0 returns an error as well. */
             && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
     {
         /* level_count == 0 returns an error as well. */
-        if (level_count != 1 || layer_count != 1)
+        if (level_count != 1 || layer_count != 1 || desc->resource_type == WINED3D_RTYPE_TEXTURE_3D)
         {
             if (!(desc->usage & WINED3DUSAGE_SCRATCH))
             {
         {
             if (!(desc->usage & WINED3DUSAGE_SCRATCH))
             {
-                WARN("Attempted to create a mipmapped/cube/array NPOT texture without unconditional NPOT support.\n");
+                WARN("Attempted to create a mipmapped/cube/array/volume NPOT "
+                        "texture without unconditional NPOT support.\n");
                 return WINED3DERR_INVALIDCALL;
             }
 
                 return WINED3DERR_INVALIDCALL;
             }
 
@@ -2690,7 +2656,8 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
         }
         texture->flags |= WINED3D_TEXTURE_COND_NP2;
 
         }
         texture->flags |= WINED3D_TEXTURE_COND_NP2;
 
-        if (!gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
+        if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !gl_info->supported[ARB_TEXTURE_RECTANGLE]
+                && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
         {
             const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format, desc->usage);
 
         {
             const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format, desc->usage);
 
@@ -2738,11 +2705,106 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
         TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width, pow2_height);
     }
 
         TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width, pow2_height);
     }
 
-    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, layer_count, level_count, desc,
-            flags, device, parent, parent_ops, &texture_resource_ops)))
+    format = wined3d_get_format(&device->adapter->gl_info, desc->format, desc->usage);
+    for (i = 0; i < layer_count; ++i)
+    {
+        for (j = 0; j < level_count; ++j)
+        {
+            unsigned int idx = i * level_count + j;
+
+            size = wined3d_format_calculate_size(format, device->surface_alignment,
+                    max(1, desc->width >> j), max(1, desc->height >> j), max(1, desc->depth >> j));
+            texture->sub_resources[idx].offset = offset;
+            texture->sub_resources[idx].size = size;
+            offset += size;
+        }
+        offset = (offset + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1);
+    }
+
+    if (!offset)
+        return WINED3DERR_INVALIDCALL;
+
+    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
+            desc->multisample_type, desc->multisample_quality, desc->usage, desc->access,
+            desc->width, desc->height, desc->depth, offset, parent, parent_ops, &texture_resource_ops)))
+    {
+        static unsigned int once;
+
+        /* DXTn 3D textures are not supported. Do not write the ERR for them. */
+        if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3
+                || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5)
+                && !(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE)
+                && desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !once++)
+            ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n");
+
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        return hr;
+    }
+    wined3d_resource_update_draw_binding(&texture->resource);
+    if ((flags & WINED3D_TEXTURE_CREATE_MAPPABLE) || desc->format == WINED3DFMT_D16_LOCKABLE)
+        texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
+
+    texture->texture_ops = texture_ops;
+
+    texture->layer_count = layer_count;
+    texture->level_count = level_count;
+    texture->lod = 0;
+    texture->flags |= WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS;
+    if (flags & WINED3D_TEXTURE_CREATE_GET_DC_LENIENT)
+        texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_GET_DC_LENIENT;
+    if (flags & (WINED3D_TEXTURE_CREATE_GET_DC | WINED3D_TEXTURE_CREATE_GET_DC_LENIENT))
+        texture->flags |= WINED3D_TEXTURE_GET_DC;
+    if (flags & WINED3D_TEXTURE_CREATE_DISCARD)
+        texture->flags |= WINED3D_TEXTURE_DISCARD;
+    if (flags & WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS)
+    {
+        if (!(texture->resource.format_flags & WINED3DFMT_FLAG_GEN_MIPMAP))
+            WARN("Format doesn't support mipmaps generation, "
+                    "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n");
+        else
+            texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS;
+    }
+
+    list_init(&texture->renderbuffers);
+
+    switch (desc->resource_type)
     {
     {
-        WARN("Failed to initialize texture, returning %#x.\n", hr);
-        return hr;
+        case WINED3D_RTYPE_TEXTURE_1D:
+            if (layer_count > 1)
+                texture->target = GL_TEXTURE_1D_ARRAY;
+            else
+                texture->target = GL_TEXTURE_1D;
+            break;
+
+        case WINED3D_RTYPE_TEXTURE_2D:
+            if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP)
+            {
+                texture->target = GL_TEXTURE_CUBE_MAP_ARB;
+            }
+            else if (desc->multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
+            {
+                if (layer_count > 1)
+                    texture->target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+                else
+                    texture->target = GL_TEXTURE_2D_MULTISAMPLE;
+            }
+            else
+            {
+                if (layer_count > 1)
+                    texture->target = GL_TEXTURE_2D_ARRAY;
+                else
+                    texture->target = GL_TEXTURE_2D;
+            }
+            break;
+
+        case WINED3D_RTYPE_TEXTURE_3D:
+            texture->target = GL_TEXTURE_3D;
+            break;
+
+        default:
+            ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type));
+            wined3d_texture_cleanup_sync(texture);
+            return WINED3DERR_INVALIDCALL;
     }
 
     /* Precalculated scaling for 'faked' non power of two texture coords. */
     }
 
     /* Precalculated scaling for 'faked' non power of two texture coords. */
@@ -2753,37 +2815,16 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
         texture->flags &= ~(WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS);
         texture->target = GL_TEXTURE_RECTANGLE_ARB;
     }
         texture->flags &= ~(WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS);
         texture->target = GL_TEXTURE_RECTANGLE_ARB;
     }
+    else if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
+    {
+        texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
+        texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
+        texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
+    }
     else
     {
     else
     {
-        if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED)
-        {
-            texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
-            texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
-            texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
-        }
-        else
-        {
-            texture->pow2_matrix[0] = 1.0f;
-            texture->pow2_matrix[5] = 1.0f;
-        }
-        if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP)
-        {
-            texture->target = GL_TEXTURE_CUBE_MAP_ARB;
-        }
-        else if (desc->multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
-        {
-            if (layer_count > 1)
-                texture->target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
-            else
-                texture->target = GL_TEXTURE_2D_MULTISAMPLE;
-        }
-        else
-        {
-            if (layer_count > 1)
-                texture->target = GL_TEXTURE_2D_ARRAY;
-            else
-                texture->target = GL_TEXTURE_2D;
-        }
+        texture->pow2_matrix[0] = 1.0f;
+        texture->pow2_matrix[5] = 1.0f;
     }
     texture->pow2_matrix[10] = 1.0f;
     texture->pow2_matrix[15] = 1.0f;
     }
     texture->pow2_matrix[10] = 1.0f;
     texture->pow2_matrix[15] = 1.0f;
@@ -2792,9 +2833,19 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     if (wined3d_texture_use_pbo(texture, gl_info))
         texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
 
     if (wined3d_texture_use_pbo(texture, gl_info))
         texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
 
+    if ((desc->resource_type != WINED3D_RTYPE_TEXTURE_3D
+            && !(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
+            || !wined3d_texture_use_pbo(texture, gl_info))
+    {
+        if (!wined3d_resource_allocate_sysmem(&texture->resource))
+        {
+            wined3d_texture_cleanup_sync(texture);
+            return E_OUTOFMEMORY;
+        }
+    }
+
     sub_count = level_count * layer_count;
     sub_count = level_count * layer_count;
-    if (sub_count / layer_count != level_count
-            || !(surfaces = heap_calloc(sub_count, sizeof(*surfaces))))
+    if (sub_count / layer_count != level_count)
     {
         wined3d_texture_cleanup_sync(texture);
         return E_OUTOFMEMORY;
     {
         wined3d_texture_cleanup_sync(texture);
         return E_OUTOFMEMORY;
@@ -2804,7 +2855,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     {
         if (!(texture->overlay_info = heap_calloc(sub_count, sizeof(*texture->overlay_info))))
         {
     {
         if (!(texture->overlay_info = heap_calloc(sub_count, sizeof(*texture->overlay_info))))
         {
-            heap_free(surfaces);
             wined3d_texture_cleanup_sync(texture);
             return E_OUTOFMEMORY;
         }
             wined3d_texture_cleanup_sync(texture);
             return E_OUTOFMEMORY;
         }
@@ -2816,52 +2866,44 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
         }
     }
 
         }
     }
 
-    /* Generate all the surfaces. */
-    for (i = 0; i < texture->level_count; ++i)
+    /* Generate all sub-resources. */
+    for (i = 0; i < sub_count; ++i)
     {
     {
-        for (j = 0; j < texture->layer_count; ++j)
+        struct wined3d_texture_sub_resource *sub_resource;
+
+        sub_resource = &texture->sub_resources[i];
+        sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+        if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D
+                && !(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
         {
         {
-            struct wined3d_texture_sub_resource *sub_resource;
-            unsigned int idx = j * texture->level_count + i;
-            struct wined3d_surface *surface;
-
-            surface = &surfaces[idx];
-            surface->container = texture;
-            surface->texture_level = i;
-            surface->texture_layer = j;
-            list_init(&surface->renderbuffers);
-
-            sub_resource = &texture->sub_resources[idx];
-            sub_resource->locations = WINED3D_LOCATION_DISCARDED;
-            sub_resource->u.surface = surface;
-            if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
-            {
-                wined3d_texture_validate_location(texture, idx, WINED3D_LOCATION_SYSMEM);
-                wined3d_texture_invalidate_location(texture, idx, ~WINED3D_LOCATION_SYSMEM);
-            }
+            wined3d_texture_validate_location(texture, i, WINED3D_LOCATION_SYSMEM);
+            wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_SYSMEM);
+        }
 
 
-            if (FAILED(hr = device_parent->ops->surface_created(device_parent,
-                    texture, idx, &sub_resource->parent, &sub_resource->parent_ops)))
-            {
-                WARN("Failed to create surface parent, hr %#x.\n", hr);
-                sub_resource->parent = NULL;
-                wined3d_texture_cleanup_sync(texture);
-                return hr;
-            }
+        if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent,
+                desc->resource_type, texture, i, &sub_resource->parent, &sub_resource->parent_ops)))
+        {
+            WARN("Failed to create sub-resource parent, hr %#x.\n", hr);
+            sub_resource->parent = NULL;
+            wined3d_texture_cleanup_sync(texture);
+            return hr;
+        }
+
+        TRACE("parent %p, parent_ops %p.\n", sub_resource->parent, sub_resource->parent_ops);
 
 
-            TRACE("parent %p, parent_ops %p.\n", sub_resource->parent, sub_resource->parent_ops);
+        TRACE("Created sub-resource %u (level %u, layer %u).\n",
+                i, i % texture->level_count, i / texture->level_count);
 
 
-            TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface);
+        if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
+        {
+            struct wined3d_texture_idx texture_idx = {texture, i};
 
 
-            if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
+            wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
+            device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
+            if (!texture->dc_info || !texture->dc_info[i].dc)
             {
             {
-                wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
-                device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
-                if (!surface->dc)
-                {
-                    wined3d_texture_cleanup_sync(texture);
-                    return WINED3DERR_INVALIDCALL;
-                }
+                wined3d_texture_cleanup_sync(texture);
+                return WINED3DERR_INVALIDCALL;
             }
         }
     }
             }
         }
     }
@@ -2869,88 +2911,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     return WINED3D_OK;
 }
 
     return WINED3D_OK;
 }
 
-/* This call just uploads data, the caller is responsible for binding the
- * correct texture. */
-/* Context activation is done by the caller. */
-static void texture3d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_box *box,
-        const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch)
-{
-    const struct wined3d_format *format = texture->resource.format;
-    unsigned int level = sub_resource_idx % texture->level_count;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    unsigned int x, y, z, update_w, update_h, update_d;
-    unsigned int dst_row_pitch, dst_slice_pitch;
-    unsigned int width, height, depth;
-    const void *mem = data->addr;
-    void *converted_mem = NULL;
-
-    TRACE("texture %p, sub_resource_idx %u, context %p, box %s, data {%#x:%p}, row_pitch %#x, slice_pitch %#x.\n",
-            texture, sub_resource_idx, context, debug_box(box),
-            data->buffer_object, data->addr, row_pitch, slice_pitch);
-
-    width = wined3d_texture_get_level_width(texture, level);
-    height = wined3d_texture_get_level_height(texture, level);
-    depth = wined3d_texture_get_level_depth(texture, level);
-
-    if (!box)
-    {
-        x = y = z = 0;
-        update_w = width;
-        update_h = height;
-        update_d = depth;
-    }
-    else
-    {
-        x = box->left;
-        y = box->top;
-        z = box->front;
-        update_w = box->right - box->left;
-        update_h = box->bottom - box->top;
-        update_d = box->back - box->front;
-    }
-
-    if (format->conv_byte_count)
-    {
-        if (data->buffer_object)
-            ERR("Loading a converted texture from a PBO.\n");
-        if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
-            ERR("Converting a block-based format.\n");
-
-        dst_row_pitch = update_w * format->conv_byte_count;
-        dst_slice_pitch = dst_row_pitch * update_h;
-
-        converted_mem = heap_calloc(update_d, dst_slice_pitch);
-        format->upload(data->addr, converted_mem, row_pitch, slice_pitch,
-                dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d);
-        mem = converted_mem;
-    }
-    else
-    {
-        wined3d_texture_get_pitch(texture, sub_resource_idx, &dst_row_pitch, &dst_slice_pitch);
-        if (row_pitch != dst_row_pitch || slice_pitch != dst_slice_pitch)
-            FIXME("Ignoring row/slice pitch (%u/%u).\n", row_pitch, slice_pitch);
-    }
-
-    if (data->buffer_object)
-    {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object));
-        checkGLcall("glBindBuffer");
-    }
-
-    GL_EXTCALL(glTexSubImage3D(GL_TEXTURE_3D, level, x, y, z,
-            update_w, update_h, update_d, format->glFormat, format->glType, mem));
-    checkGLcall("glTexSubImage3D");
-
-    if (data->buffer_object)
-    {
-        GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
-        checkGLcall("glBindBuffer");
-    }
-
-    heap_free(converted_mem);
-}
-
 /* Context activation is done by the caller. */
 static void texture3d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         const struct wined3d_context *context, const struct wined3d_bo_address *data)
 /* Context activation is done by the caller. */
 static void texture3d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         const struct wined3d_context *context, const struct wined3d_bo_address *data)
@@ -2990,6 +2950,7 @@ static void texture3d_srgb_transfer(struct wined3d_texture *texture, unsigned in
     struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
     unsigned int row_pitch, slice_pitch;
     struct wined3d_bo_address data;
     struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
     unsigned int row_pitch, slice_pitch;
     struct wined3d_bo_address data;
+    struct wined3d_box src_box;
 
     /* Optimisations are possible, but the effort should be put into either
      * implementing EXT_SRGB_DECODE in the driver or finding out why we
 
     /* Optimisations are possible, but the effort should be put into either
      * implementing EXT_SRGB_DECODE in the driver or finding out why we
@@ -3003,11 +2964,12 @@ static void texture3d_srgb_transfer(struct wined3d_texture *texture, unsigned in
         return;
 
     wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
         return;
 
     wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
+    wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box);
     wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb);
     texture3d_download_data(texture, sub_resource_idx, context, &data);
     wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb);
     wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb);
     texture3d_download_data(texture, sub_resource_idx, context, &data);
     wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb);
-    texture3d_upload_data(texture, sub_resource_idx, context,
-            NULL, wined3d_const_bo_address(&data), row_pitch, slice_pitch);
+    wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format,
+            &src_box, wined3d_const_bo_address(&data), row_pitch, slice_pitch, 0, 0, 0, FALSE);
 
     heap_free(data.addr);
 }
 
     heap_free(data.addr);
 }
@@ -3029,23 +2991,27 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in
             if (sub_resource->locations & WINED3D_LOCATION_SYSMEM)
             {
                 struct wined3d_const_bo_address data = {0, texture->resource.heap_memory};
             if (sub_resource->locations & WINED3D_LOCATION_SYSMEM)
             {
                 struct wined3d_const_bo_address data = {0, texture->resource.heap_memory};
+                struct wined3d_box src_box;
+
                 data.addr += sub_resource->offset;
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
                 data.addr += sub_resource->offset;
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
-                texture3d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch);
+                wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box);
+                wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format,
+                        &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE);
             }
             else if (sub_resource->locations & WINED3D_LOCATION_BUFFER)
             {
             }
             else if (sub_resource->locations & WINED3D_LOCATION_BUFFER)
             {
-#if !defined(STAGING_CSMT)
                 struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL};
                 struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL};
-#else  /* STAGING_CSMT */
-                struct wined3d_const_bo_address data = {sub_resource->buffer->name, NULL};
-#endif /* STAGING_CSMT */
+                struct wined3d_box src_box;
+
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
                 wined3d_texture_bind_and_dirtify(texture, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch);
-                texture3d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch);
+                wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box);
+                wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format,
+                        &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE);
             }
             else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
             {
             }
             else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
             {
@@ -3087,11 +3053,7 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in
         case WINED3D_LOCATION_BUFFER:
             if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
             {
         case WINED3D_LOCATION_BUFFER:
             if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
             {
-#if !defined(STAGING_CSMT)
                 struct wined3d_bo_address data = {sub_resource->buffer_object, NULL};
                 struct wined3d_bo_address data = {sub_resource->buffer_object, NULL};
-#else  /* STAGING_CSMT */
-                struct wined3d_bo_address data = {sub_resource->buffer->name, NULL};
-#endif /* STAGING_CSMT */
 
                 if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
                     wined3d_texture_bind_and_dirtify(texture, context, FALSE);
 
                 if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)
                     wined3d_texture_bind_and_dirtify(texture, context, FALSE);
@@ -3117,148 +3079,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in
     return TRUE;
 }
 
     return TRUE;
 }
 
-static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
-{
-    const struct wined3d_format *format = texture->resource.format;
-    GLenum internal = srgb ? format->glGammaInternal : format->glInternal;
-    unsigned int sub_count = texture->level_count * texture->layer_count;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    unsigned int i;
-
-    wined3d_texture_bind_and_dirtify(texture, context, srgb);
-
-    if (wined3d_texture_use_immutable_storage(texture, gl_info))
-    {
-        GL_EXTCALL(glTexStorage3D(GL_TEXTURE_3D, texture->level_count, internal,
-                wined3d_texture_get_level_width(texture, 0),
-                wined3d_texture_get_level_height(texture, 0),
-                wined3d_texture_get_level_depth(texture, 0)));
-        checkGLcall("glTexStorage3D");
-    }
-    else
-    {
-        for (i = 0; i < sub_count; ++i)
-        {
-            GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D, i, internal,
-                    wined3d_texture_get_level_width(texture, i),
-                    wined3d_texture_get_level_height(texture, i),
-                    wined3d_texture_get_level_depth(texture, i),
-                    0, format->glFormat, format->glType, NULL));
-            checkGLcall("glTexImage3D");
-        }
-    }
-}
-
-static void texture3d_cleanup_sub_resources(struct wined3d_texture *texture)
-{
-}
-
 static const struct wined3d_texture_ops texture3d_ops =
 {
 static const struct wined3d_texture_ops texture3d_ops =
 {
-    texture3d_upload_data,
     texture3d_load_location,
     texture3d_load_location,
-    texture3d_prepare_texture,
-    texture3d_cleanup_sub_resources,
 };
 
 };
 
-static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
-        UINT layer_count, UINT level_count, DWORD flags, struct wined3d_device *device, void *parent,
-        const struct wined3d_parent_ops *parent_ops)
-{
-    struct wined3d_device_parent *device_parent = device->device_parent;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    unsigned int i;
-    HRESULT hr;
-
-    if (layer_count != 1)
-    {
-        ERR("Invalid layer count for volume texture.\n");
-        return E_INVALIDARG;
-    }
-
-    /* TODO: It should only be possible to create textures for formats
-     * that are reported as supported. */
-    if (WINED3DFMT_UNKNOWN >= desc->format)
-    {
-        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
-        return WINED3DERR_INVALIDCALL;
-    }
-
-    if (!gl_info->supported[EXT_TEXTURE3D])
-    {
-        WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture);
-        return WINED3DERR_INVALIDCALL;
-    }
-
-    if (desc->usage & WINED3DUSAGE_DYNAMIC && (wined3d_resource_access_is_managed(desc->access)
-            || desc->usage & WINED3DUSAGE_SCRATCH))
-    {
-        WARN("Attempted to create a DYNAMIC texture with access %s.\n",
-                wined3d_debug_resource_access(desc->access));
-        return WINED3DERR_INVALIDCALL;
-    }
-
-    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
-    {
-        if (!is_power_of_two(desc->width) || !is_power_of_two(desc->height) || !is_power_of_two(desc->depth))
-        {
-            if (desc->usage & WINED3DUSAGE_SCRATCH)
-            {
-                WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n");
-            }
-            else
-            {
-                WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n",
-                        desc->width, desc->height, desc->depth);
-                return WINED3DERR_INVALIDCALL;
-            }
-        }
-    }
-
-    if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, level_count, desc,
-            flags, device, parent, parent_ops, &texture_resource_ops)))
-    {
-        WARN("Failed to initialize texture, returning %#x.\n", hr);
-        return hr;
-    }
-
-    texture->pow2_matrix[0] = 1.0f;
-    texture->pow2_matrix[5] = 1.0f;
-    texture->pow2_matrix[10] = 1.0f;
-    texture->pow2_matrix[15] = 1.0f;
-    texture->target = GL_TEXTURE_3D;
-
-    if (wined3d_texture_use_pbo(texture, gl_info))
-    {
-        wined3d_resource_free_sysmem(&texture->resource);
-        texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
-    }
-
-    /* Generate all the sub resources. */
-    for (i = 0; i < texture->level_count; ++i)
-    {
-        struct wined3d_texture_sub_resource *sub_resource;
-
-        sub_resource = &texture->sub_resources[i];
-        sub_resource->locations = WINED3D_LOCATION_DISCARDED;
-
-        if (FAILED(hr = device_parent->ops->volume_created(device_parent,
-                texture, i, &sub_resource->parent, &sub_resource->parent_ops)))
-        {
-            WARN("Failed to create volume parent, hr %#x.\n", hr);
-            sub_resource->parent = NULL;
-            wined3d_texture_cleanup_sync(texture);
-            return hr;
-        }
-
-        TRACE("parent %p, parent_ops %p.\n", parent, parent_ops);
-
-        TRACE("Created volume level %u.\n", i);
-    }
-
-    return WINED3D_OK;
-}
-
 HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
         const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
 HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
         const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
@@ -3294,19 +3119,8 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned
     if (dst_texture->sub_resources[dst_sub_resource_idx].map_count
             || src_texture->sub_resources[src_sub_resource_idx].map_count)
     {
     if (dst_texture->sub_resources[dst_sub_resource_idx].map_count
             || src_texture->sub_resources[src_sub_resource_idx].map_count)
     {
-#if !defined(STAGING_CSMT)
         WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n");
         return WINEDDERR_SURFACEBUSY;
         WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n");
         return WINEDDERR_SURFACEBUSY;
-#else  /* STAGING_CSMT */
-        struct wined3d_device *device = dst_texture->resource.device;
-        device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
-        if (dst_texture->sub_resources[dst_sub_resource_idx].map_count
-                || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count))
-        {
-            WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n");
-            return WINEDDERR_SURFACEBUSY;
-        }
-#endif /* STAGING_CSMT */
     }
 
     if ((src_format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
     }
 
     if ((src_format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
@@ -3337,7 +3151,7 @@ HRESULT CDECL wined3d_texture_get_overlay_position(const struct wined3d_texture
     }
 
     overlay = &texture->overlay_info[sub_resource_idx];
     }
 
     overlay = &texture->overlay_info[sub_resource_idx];
-    if (!overlay->dst)
+    if (!overlay->dst_texture)
     {
         TRACE("Overlay not visible.\n");
         *x = 0;
     {
         TRACE("Overlay not visible.\n");
         *x = 0;
@@ -3380,9 +3194,8 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un
         const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         const RECT *dst_rect, DWORD flags)
 {
         const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         const RECT *dst_rect, DWORD flags)
 {
-    struct wined3d_texture_sub_resource *sub_resource, *dst_sub_resource;
-    struct wined3d_surface *surface, *dst_surface;
     struct wined3d_overlay_info *overlay;
     struct wined3d_overlay_info *overlay;
+    unsigned int level, dst_level;
 
     TRACE("texture %p, sub_resource_idx %u, src_rect %s, dst_texture %p, "
             "dst_sub_resource_idx %u, dst_rect %s, flags %#x.\n",
 
     TRACE("texture %p, sub_resource_idx %u, src_rect %s, dst_texture %p, "
             "dst_sub_resource_idx %u, dst_rect %s, flags %#x.\n",
@@ -3390,14 +3203,14 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un
             dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), flags);
 
     if (!(texture->resource.usage & WINED3DUSAGE_OVERLAY) || texture->resource.type != WINED3D_RTYPE_TEXTURE_2D
             dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), flags);
 
     if (!(texture->resource.usage & WINED3DUSAGE_OVERLAY) || texture->resource.type != WINED3D_RTYPE_TEXTURE_2D
-            || !(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
+            || sub_resource_idx >= texture->level_count * texture->layer_count)
     {
         WARN("Invalid sub-resource specified.\n");
         return WINEDDERR_NOTAOVERLAYSURFACE;
     }
 
     if (!dst_texture || dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D
     {
         WARN("Invalid sub-resource specified.\n");
         return WINEDDERR_NOTAOVERLAYSURFACE;
     }
 
     if (!dst_texture || dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D
-            || !(dst_sub_resource = wined3d_texture_get_sub_resource(dst_texture, dst_sub_resource_idx)))
+            || dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count)
     {
         WARN("Invalid destination sub-resource specified.\n");
         return WINED3DERR_INVALIDCALL;
     {
         WARN("Invalid destination sub-resource specified.\n");
         return WINED3DERR_INVALIDCALL;
@@ -3405,33 +3218,35 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un
 
     overlay = &texture->overlay_info[sub_resource_idx];
 
 
     overlay = &texture->overlay_info[sub_resource_idx];
 
-    surface = sub_resource->u.surface;
+    level = sub_resource_idx % texture->level_count;
     if (src_rect)
         overlay->src_rect = *src_rect;
     else
         SetRect(&overlay->src_rect, 0, 0,
     if (src_rect)
         overlay->src_rect = *src_rect;
     else
         SetRect(&overlay->src_rect, 0, 0,
-                wined3d_texture_get_level_width(texture, surface->texture_level),
-                wined3d_texture_get_level_height(texture, surface->texture_level));
+                wined3d_texture_get_level_width(texture, level),
+                wined3d_texture_get_level_height(texture, level));
 
 
-    dst_surface = dst_sub_resource->u.surface;
+    dst_level = dst_sub_resource_idx % dst_texture->level_count;
     if (dst_rect)
         overlay->dst_rect = *dst_rect;
     else
         SetRect(&overlay->dst_rect, 0, 0,
     if (dst_rect)
         overlay->dst_rect = *dst_rect;
     else
         SetRect(&overlay->dst_rect, 0, 0,
-                wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level),
-                wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level));
+                wined3d_texture_get_level_width(dst_texture, dst_level),
+                wined3d_texture_get_level_height(dst_texture, dst_level));
 
 
-    if (overlay->dst && (overlay->dst != dst_surface || flags & WINEDDOVER_HIDE))
+    if (overlay->dst_texture && (overlay->dst_texture != dst_texture
+            || overlay->dst_sub_resource_idx != dst_sub_resource_idx || flags & WINEDDOVER_HIDE))
     {
     {
-        overlay->dst = NULL;
+        overlay->dst_texture = NULL;
         list_remove(&overlay->entry);
     }
 
     if (flags & WINEDDOVER_SHOW)
     {
         list_remove(&overlay->entry);
     }
 
     if (flags & WINEDDOVER_SHOW)
     {
-        if (overlay->dst != dst_surface)
+        if (overlay->dst_texture != dst_texture || overlay->dst_sub_resource_idx != dst_sub_resource_idx)
         {
         {
-            overlay->dst = dst_surface;
+            overlay->dst_texture = dst_texture;
+            overlay->dst_sub_resource_idx = dst_sub_resource_idx;
             list_add_tail(&texture->overlay_info[dst_sub_resource_idx].overlays, &overlay->entry);
         }
     }
             list_add_tail(&texture->overlay_info[dst_sub_resource_idx].overlays, &overlay->entry);
         }
     }
@@ -3440,7 +3255,7 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un
         /* Tests show that the rectangles are erased on hide. */
         SetRectEmpty(&overlay->src_rect);
         SetRectEmpty(&overlay->dst_rect);
         /* Tests show that the rectangles are erased on hide. */
         SetRectEmpty(&overlay->src_rect);
         SetRectEmpty(&overlay->dst_rect);
-        overlay->dst = NULL;
+        overlay->dst_texture = NULL;
     }
 
     return WINED3D_OK;
     }
 
     return WINED3D_OK;
@@ -3512,6 +3327,7 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         UINT layer_count, UINT level_count, DWORD flags, const struct wined3d_sub_resource_data *data,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
 {
         UINT layer_count, UINT level_count, DWORD flags, const struct wined3d_sub_resource_data *data,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
 {
+    const struct wined3d_texture_ops *texture_ops;
     struct wined3d_texture *object;
     HRESULT hr;
 
     struct wined3d_texture *object;
     HRESULT hr;
 
@@ -3558,31 +3374,28 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         }
     }
 
         }
     }
 
-    if (!(object = heap_alloc_zero(FIELD_OFFSET(struct wined3d_texture,
-            sub_resources[level_count * layer_count]))))
-        return E_OUTOFMEMORY;
-
     switch (desc->resource_type)
     {
         case WINED3D_RTYPE_TEXTURE_1D:
     switch (desc->resource_type)
     {
         case WINED3D_RTYPE_TEXTURE_1D:
-            hr = texture1d_init(object, desc, layer_count, level_count, device, parent, parent_ops);
+            texture_ops = &texture1d_ops;
             break;
             break;
-
         case WINED3D_RTYPE_TEXTURE_2D:
         case WINED3D_RTYPE_TEXTURE_2D:
-            hr = texture_init(object, desc, layer_count, level_count, flags, device, parent, parent_ops);
+            texture_ops = &texture2d_ops;
             break;
             break;
-
         case WINED3D_RTYPE_TEXTURE_3D:
         case WINED3D_RTYPE_TEXTURE_3D:
-            hr = volumetexture_init(object, desc, layer_count, level_count, flags, device, parent, parent_ops);
+            texture_ops = &texture3d_ops;
             break;
             break;
-
         default:
             ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type));
         default:
             ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type));
-            hr = WINED3DERR_INVALIDCALL;
-            break;
+            return WINED3DERR_INVALIDCALL;
     }
 
     }
 
-    if (FAILED(hr))
+    if (!(object = heap_alloc_zero(FIELD_OFFSET(struct wined3d_texture,
+            sub_resources[level_count * layer_count]))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_texture_init(object, desc, layer_count,
+            level_count, flags, device, parent, parent_ops, texture_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         heap_free(object);
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         heap_free(object);
@@ -3610,7 +3423,7 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         for (i = 0; i < sub_count; ++i)
         {
             wined3d_device_update_sub_resource(device, &object->resource,
         for (i = 0; i < sub_count; ++i)
         {
             wined3d_device_update_sub_resource(device, &object->resource,
-                    i, NULL, data[i].data, data[i].row_pitch, data[i].slice_pitch);
+                    i, NULL, data[i].data, data[i].row_pitch, data[i].slice_pitch, 0);
         }
     }
 
         }
     }
 
@@ -3624,7 +3437,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
 {
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
 {
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_surface *surface;
+    struct wined3d_dc_info *dc_info;
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
 
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
 
@@ -3644,25 +3457,25 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
-    surface = sub_resource->u.surface;
-
     if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         return WINED3DERR_INVALIDCALL;
 
     if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         return WINED3DERR_INVALIDCALL;
 
-    if (!surface->dc)
+    if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc)
     {
     {
-        wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
+        struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
+
+        wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
+        if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc)
+            return WINED3DERR_INVALIDCALL;
     }
     }
-    if (!surface->dc)
-        return WINED3DERR_INVALIDCALL;
 
     if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         texture->flags |= WINED3D_TEXTURE_DC_IN_USE;
     ++texture->resource.map_count;
     ++sub_resource->map_count;
 
 
     if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         texture->flags |= WINED3D_TEXTURE_DC_IN_USE;
     ++texture->resource.map_count;
     ++sub_resource->map_count;
 
-    *dc = surface->dc;
+    *dc = dc_info[sub_resource_idx].dc;
     TRACE("Returning dc %p.\n", *dc);
 
     return WINED3D_OK;
     TRACE("Returning dc %p.\n", *dc);
 
     return WINED3D_OK;
@@ -3672,7 +3485,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
 {
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
 {
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_surface *surface;
+    struct wined3d_dc_info *dc_info;
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
 
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
 
@@ -3685,20 +3498,21 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
         return WINED3DERR_INVALIDCALL;
     }
 
         return WINED3DERR_INVALIDCALL;
     }
 
-    surface = sub_resource->u.surface;
-
     if (!(texture->flags & (WINED3D_TEXTURE_GET_DC_LENIENT | WINED3D_TEXTURE_DC_IN_USE)))
         return WINED3DERR_INVALIDCALL;
 
     if (!(texture->flags & (WINED3D_TEXTURE_GET_DC_LENIENT | WINED3D_TEXTURE_DC_IN_USE)))
         return WINED3DERR_INVALIDCALL;
 
-    if (surface->dc != dc)
+    if (!(dc_info = texture->dc_info) || dc_info[sub_resource_idx].dc != dc)
     {
     {
-        WARN("Application tries to release invalid DC %p, surface DC is %p.\n", dc, surface->dc);
+        WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n",
+                dc, dc_info ? dc_info[sub_resource_idx].dc : NULL);
         return WINED3DERR_INVALIDCALL;
     }
 
     if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D))
     {
         return WINED3DERR_INVALIDCALL;
     }
 
     if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D))
     {
-        wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface);
+        struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
+
+        wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx);
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
     }
 
         device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
     }
 
@@ -3710,3 +3524,49 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
 
     return WINED3D_OK;
 }
 
     return WINED3D_OK;
 }
+
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
+{
+    unsigned int src_row_pitch, src_slice_pitch;
+    unsigned int update_w, update_h, update_d;
+    unsigned int src_level, dst_level;
+    struct wined3d_context *context;
+    struct wined3d_bo_address data;
+
+    TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
+            "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
+            dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z,
+            src_texture, src_sub_resource_idx, debug_box(src_box));
+
+    context = context_acquire(dst_texture->resource.device, NULL, 0);
+
+    /* Only load the sub-resource for partial updates. For newly allocated
+     * textures the texture wouldn't be the current location, and we'd upload
+     * zeroes just to overwrite them again. */
+    update_w = src_box->right - src_box->left;
+    update_h = src_box->bottom - src_box->top;
+    update_d = src_box->back - src_box->front;
+    dst_level = dst_sub_resource_idx % dst_texture->level_count;
+    if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
+            && update_h == wined3d_texture_get_level_height(dst_texture, dst_level)
+            && update_d == wined3d_texture_get_level_depth(dst_texture, dst_level))
+        wined3d_texture_prepare_texture(dst_texture, context, FALSE);
+    else
+        wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
+
+    src_level = src_sub_resource_idx % src_texture->level_count;
+    wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
+            src_texture->sub_resources[src_sub_resource_idx].locations);
+    wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
+
+    wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
+            src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, FALSE);
+
+    context_release(context);
+
+    wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
+    wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
+}
index b48293e..9196038 100644 (file)
@@ -122,7 +122,6 @@ static const struct wined3d_format_channels formats[] =
     /* Bump mapping stuff */
     {WINED3DFMT_R5G5_SNORM_L6_UNORM,        5,  5,  0,  0,   0,  5,  0,  0,    2,   0,     0},
     {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,      8,  8,  0,  0,   0,  8,  0,  0,    4,   0,     0},
     /* Bump mapping stuff */
     {WINED3DFMT_R5G5_SNORM_L6_UNORM,        5,  5,  0,  0,   0,  5,  0,  0,    2,   0,     0},
     {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,      8,  8,  0,  0,   0,  8,  0,  0,    4,   0,     0},
-    {WINED3DFMT_R8G8B8A8_SNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
     {WINED3DFMT_R10G11B11_SNORM,           10, 11, 11,  0,   0, 10, 21,  0,    4,   0,     0},
     {WINED3DFMT_R10G10B10X2_UINT,          10, 10, 10,  0,   0, 10, 20,  0,    4,   0,     0},
     {WINED3DFMT_R10G10B10X2_SNORM,         10, 10, 10,  0,   0, 10, 20,  0,    4,   0,     0},
     {WINED3DFMT_R10G11B11_SNORM,           10, 11, 11,  0,   0, 10, 21,  0,    4,   0,     0},
     {WINED3DFMT_R10G10B10X2_UINT,          10, 10, 10,  0,   0, 10, 20,  0,    4,   0,     0},
     {WINED3DFMT_R10G10B10X2_SNORM,         10, 10, 10,  0,   0, 10, 20,  0,    4,   0,     0},
@@ -133,8 +132,6 @@ static const struct wined3d_format_channels formats[] =
     {WINED3DFMT_S1_UINT_D15_UNORM,          0,  0,  0,  0,   0,  0,  0,  0,    2,  15,     1},
     {WINED3DFMT_X8D24_UNORM,                0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     0},
     {WINED3DFMT_S4X4_UINT_D24_UNORM,        0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     4},
     {WINED3DFMT_S1_UINT_D15_UNORM,          0,  0,  0,  0,   0,  0,  0,  0,    2,  15,     1},
     {WINED3DFMT_X8D24_UNORM,                0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     0},
     {WINED3DFMT_S4X4_UINT_D24_UNORM,        0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     4},
-    {WINED3DFMT_D16_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    2,  16,     0},
-    {WINED3DFMT_D32_FLOAT,                  0,  0,  0,  0,   0,  0,  0,  0,    4,  32,     0},
     {WINED3DFMT_S8_UINT_D24_FLOAT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
     /* Vendor-specific formats */
     {WINED3DFMT_ATI1N,                      0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_S8_UINT_D24_FLOAT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
     /* Vendor-specific formats */
     {WINED3DFMT_ATI1N,                      0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
@@ -895,45 +892,9 @@ static BOOL color_in_range(const struct wined3d_color_key *color_key, DWORD colo
             && color <= color_key->color_space_high_value;
 }
 
             && color <= color_key->color_space_high_value;
 }
 
-static void convert_p8_uint_b8g8r8a8_unorm(const BYTE *src, unsigned int src_pitch,
-        BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
-{
-    const BYTE *src_row;
-    unsigned int x, y;
-    DWORD *dst_row;
-
-    if (!palette)
-    {
-        /* FIXME: This should probably use the system palette. */
-        FIXME("P8 surface loaded without a palette.\n");
-
-        for (y = 0; y < height; ++y)
-        {
-            memset(&dst[dst_pitch * y], 0, width * 4);
-        }
-
-        return;
-    }
-
-    for (y = 0; y < height; ++y)
-    {
-        src_row = &src[src_pitch * y];
-        dst_row = (DWORD *)&dst[dst_pitch * y];
-        for (x = 0; x < width; ++x)
-        {
-            BYTE src_color = src_row[x];
-            dst_row[x] = 0xff000000
-                    | (palette->colors[src_color].rgbRed << 16)
-                    | (palette->colors[src_color].rgbGreen << 8)
-                    | palette->colors[src_color].rgbBlue;
-        }
-    }
-}
-
 static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
 static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
+        const struct wined3d_color_key *color_key)
 {
     const WORD *src_row;
     unsigned int x, y;
 {
     const WORD *src_row;
     unsigned int x, y;
@@ -956,7 +917,7 @@ static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsig
 
 static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
 
 static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
+        const struct wined3d_color_key *color_key)
 {
     const WORD *src_row;
     unsigned int x, y;
 {
     const WORD *src_row;
     unsigned int x, y;
@@ -979,7 +940,7 @@ static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, uns
 
 static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
 
 static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
+        const struct wined3d_color_key *color_key)
 {
     const BYTE *src_row;
     unsigned int x, y;
 {
     const BYTE *src_row;
     unsigned int x, y;
@@ -1000,7 +961,7 @@ static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsig
 
 static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
 
 static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
+        const struct wined3d_color_key *color_key)
 {
     const DWORD *src_row;
     unsigned int x, y;
 {
     const DWORD *src_row;
     unsigned int x, y;
@@ -1023,7 +984,7 @@ static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, uns
 
 static void convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
 
 static void convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
         BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
-        const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
+        const struct wined3d_color_key *color_key)
 {
     const DWORD *src_row;
     unsigned int x, y;
 {
     const DWORD *src_row;
     unsigned int x, y;
@@ -1062,10 +1023,6 @@ const struct wined3d_color_key_conversion * wined3d_format_get_color_key_convers
         {WINED3DFMT_B8G8R8X8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key }},
         {WINED3DFMT_B8G8R8A8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key }},
     };
         {WINED3DFMT_B8G8R8X8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key }},
         {WINED3DFMT_B8G8R8A8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key }},
     };
-    static const struct wined3d_color_key_conversion convert_p8 =
-    {
-        WINED3DFMT_B8G8R8A8_UNORM,  convert_p8_uint_b8g8r8a8_unorm
-    };
 
     if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY))
     {
 
     if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY))
     {
@@ -1078,13 +1035,6 @@ const struct wined3d_color_key_conversion * wined3d_format_get_color_key_convers
         FIXME("Color-keying not supported with format %s.\n", debug_d3dformat(format->id));
     }
 
         FIXME("Color-keying not supported with format %s.\n", debug_d3dformat(format->id));
     }
 
-    /* FIXME: This should check if the blitter backend can do P8 conversion,
-     * instead of checking for ARB_fragment_program. */
-    if (format->id == WINED3DFMT_P8_UINT
-            && !(texture->resource.device->adapter->gl_info.supported[ARB_FRAGMENT_PROGRAM]
-            && texture->swapchain && texture == texture->swapchain->front_buffer))
-        return &convert_p8;
-
     return NULL;
 }
 
     return NULL;
 }
 
@@ -1684,10 +1634,6 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             GL_RGBA_INTEGER,            GL_INT,                           0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
             EXT_TEXTURE_INTEGER,        NULL},
             GL_RGBA_INTEGER,            GL_INT,                           0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
             EXT_TEXTURE_INTEGER,        NULL},
-    {WINED3DFMT_R24_UNORM_X8_TYPELESS,  GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
-            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT_24_8,             0,
-            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH,
-            ARB_DEPTH_TEXTURE,          NULL},
     /* Vendor-specific formats */
     {WINED3DFMT_ATI1N,                  GL_COMPRESSED_RED_RGTC1,          GL_COMPRESSED_RED_RGTC1,                0,
             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
     /* Vendor-specific formats */
     {WINED3DFMT_ATI1N,                  GL_COMPRESSED_RED_RGTC1,          GL_COMPRESSED_RED_RGTC1,                0,
             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
@@ -2807,7 +2753,7 @@ static void query_internal_format(struct wined3d_adapter *adapter,
         struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
         struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format)
 {
         struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
         struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format)
 {
-    GLint count, multisample_types[MAX_MULTISAMPLE_TYPES];
+    GLint count, multisample_types[8];
     unsigned int i, max_log2;
     GLenum target;
 
     unsigned int i, max_log2;
     GLenum target;
 
@@ -2886,7 +2832,9 @@ static void query_internal_format(struct wined3d_adapter *adapter,
             count = 0;
             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
                     GL_NUM_SAMPLE_COUNTS, 1, &count));
             count = 0;
             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
                     GL_NUM_SAMPLE_COUNTS, 1, &count));
-            count = min(count, MAX_MULTISAMPLE_TYPES);
+            if (count > ARRAY_SIZE(multisample_types))
+                FIXME("Unexpectedly high number of multisample types %d.\n", count);
+            count = min(count, ARRAY_SIZE(multisample_types));
             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
                     GL_SAMPLES, count, multisample_types));
             checkGLcall("query sample counts");
             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
                     GL_SAMPLES, count, multisample_types));
             checkGLcall("query sample counts");
@@ -3274,8 +3222,8 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
     }
 
                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
     }
 
-    if (!gl_info->supported[APPLE_YCBCR_422] && gl_info->supported[ARB_FRAGMENT_PROGRAM]
-            && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    if (!gl_info->supported[APPLE_YCBCR_422] && (gl_info->supported[ARB_FRAGMENT_PROGRAM]
+            || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER])))
     {
         idx = get_format_idx(WINED3DFMT_YUY2);
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
     {
         idx = get_format_idx(WINED3DFMT_YUY2);
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
@@ -3284,7 +3232,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
     }
     else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM]
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
     }
     else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM]
-            || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]))
+            && (!gl_info->supported[ARB_FRAGMENT_SHADER] || !gl_info->supported[ARB_VERTEX_SHADER])))
     {
         idx = get_format_idx(WINED3DFMT_YUY2);
         gl_info->formats[idx].glInternal = 0;
     {
         idx = get_format_idx(WINED3DFMT_YUY2);
         gl_info->formats[idx].glInternal = 0;
@@ -3293,7 +3241,8 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
         gl_info->formats[idx].glInternal = 0;
     }
 
         gl_info->formats[idx].glInternal = 0;
     }
 
-    if (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM]
+            || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER]))
     {
         idx = get_format_idx(WINED3DFMT_YV12);
         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_HEIGHT_SCALE);
     {
         idx = get_format_idx(WINED3DFMT_YV12);
         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_HEIGHT_SCALE);
@@ -3342,7 +3291,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE);
     }
 
                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE);
     }
 
-    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER])
     {
         idx = get_format_idx(WINED3DFMT_P8_UINT);
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
     {
         idx = get_format_idx(WINED3DFMT_P8_UINT);
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
@@ -4496,7 +4445,6 @@ const char *debug_d3drenderstate(enum wined3d_render_state state)
         D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
         D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
         D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
         D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
         D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
         D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
-        D3DSTATE_TO_STR(WINED3D_RS_DEPTHCLIP);
 #undef D3DSTATE_TO_STR
         default:
             FIXME("Unrecognized %u render state!\n", state);
 #undef D3DSTATE_TO_STR
         default:
             FIXME("Unrecognized %u render state!\n", state);
@@ -4715,8 +4663,8 @@ const char *debug_d3dstate(DWORD state)
         return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
     if (STATE_IS_MATERIAL(state))
         return "STATE_MATERIAL";
         return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
     if (STATE_IS_MATERIAL(state))
         return "STATE_MATERIAL";
-    if (STATE_IS_FRONTFACE(state))
-        return "STATE_FRONTFACE";
+    if (STATE_IS_RASTERIZER(state))
+        return "STATE_RASTERIZER";
     if (STATE_IS_POINTSPRITECOORDORIGIN(state))
         return "STATE_POINTSPRITECOORDORIGIN";
     if (STATE_IS_BASEVERTEXINDEX(state))
     if (STATE_IS_POINTSPRITECOORDORIGIN(state))
         return "STATE_POINTSPRITECOORDORIGIN";
     if (STATE_IS_BASEVERTEXINDEX(state))
@@ -4928,10 +4876,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
     if (context->last_was_rhw)
     {
         /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
     if (context->last_was_rhw)
     {
         /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
-        float x = state->viewport.x;
-        float y = state->viewport.y;
-        float w = state->viewport.width;
-        float h = state->viewport.height;
+        float x = state->viewports[0].x;
+        float y = state->viewports[0].y;
+        float w = state->viewports[0].width;
+        float h = state->viewports[0].height;
         float x_scale = 2.0f / w;
         float x_offset = (center_offset - (2.0f * x) - w) / w;
         float y_scale = flip ? 2.0f / h : 2.0f / -h;
         float x_scale = 2.0f / w;
         float x_offset = (center_offset - (2.0f * x) - w) / w;
         float y_scale = flip ? 2.0f / h : 2.0f / -h;
@@ -4955,10 +4903,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
     else
     {
         float y_scale = flip ? -1.0f : 1.0f;
     else
     {
         float y_scale = flip ? -1.0f : 1.0f;
-        float x_offset = center_offset / state->viewport.width;
+        float x_offset = center_offset / state->viewports[0].width;
         float y_offset = flip
         float y_offset = flip
-                ? center_offset / state->viewport.height
-                : -center_offset / state->viewport.height;
+                ? center_offset / state->viewports[0].height
+                : -center_offset / state->viewports[0].height;
         float z_scale = clip_control ? 1.0f : 2.0f;
         float z_offset = clip_control ? 0.0f : -1.0f;
         const struct wined3d_matrix projection =
         float z_scale = clip_control ? 1.0f : 2.0f;
         float z_offset = clip_control ? 0.0f : -1.0f;
         const struct wined3d_matrix projection =
@@ -5158,9 +5106,10 @@ void get_pointsize(const struct wined3d_context *context, const struct wined3d_s
     b.d = state->render_states[WINED3D_RS_POINTSCALE_B];
     c.d = state->render_states[WINED3D_RS_POINTSCALE_C];
 
     b.d = state->render_states[WINED3D_RS_POINTSCALE_B];
     c.d = state->render_states[WINED3D_RS_POINTSCALE_C];
 
+    /* Always use first viewport, this path does not apply to d3d10/11 multiple viewports case. */
     if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
     {
     if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
     {
-        float scale_factor = state->viewport.height * state->viewport.height;
+        float scale_factor = state->viewports[0].height * state->viewports[0].height;
 
         out_att[0] = a.f / scale_factor;
         out_att[1] = b.f / scale_factor;
 
         out_att[0] = a.f / scale_factor;
         out_att[1] = b.f / scale_factor;
@@ -5797,9 +5746,9 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
             settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
             settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
             settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
             settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
             settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
             settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
-            settings->op[i].dst = resultreg;
+            settings->op[i].tmp_dst = 0;
             settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
             settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
-            settings->op[i].projected = proj_none;
+            settings->op[i].projected = WINED3D_PROJECTION_NONE;
             i++;
             break;
         }
             i++;
             break;
         }
@@ -5923,15 +5872,15 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
         {
             ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
             if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
         {
             ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
             if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
-                settings->op[i].projected = proj_count3;
+                settings->op[i].projected = WINED3D_PROJECTION_COUNT3;
             else if (ttff & WINED3D_TTFF_PROJECTED)
             else if (ttff & WINED3D_TTFF_PROJECTED)
-                settings->op[i].projected = proj_count4;
+                settings->op[i].projected = WINED3D_PROJECTION_COUNT4;
             else
             else
-                settings->op[i].projected = proj_none;
+                settings->op[i].projected = WINED3D_PROJECTION_NONE;
         }
         else
         {
         }
         else
         {
-            settings->op[i].projected = proj_none;
+            settings->op[i].projected = WINED3D_PROJECTION_NONE;
         }
 
         settings->op[i].cop = cop;
         }
 
         settings->op[i].cop = cop;
@@ -5942,11 +5891,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
         settings->op[i].aarg0 = aarg0;
         settings->op[i].aarg1 = aarg1;
         settings->op[i].aarg2 = aarg2;
         settings->op[i].aarg0 = aarg0;
         settings->op[i].aarg1 = aarg1;
         settings->op[i].aarg2 = aarg2;
-
-        if (state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP)
-            settings->op[i].dst = tempreg;
-        else
-            settings->op[i].dst = resultreg;
+        settings->op[i].tmp_dst = state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP;
     }
 
     /* Clear unsupported stages */
     }
 
     /* Clear unsupported stages */
@@ -6093,27 +6038,7 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st
     {
         switch (texture->target)
         {
     {
         switch (texture->target)
         {
-            case GL_TEXTURE_1D:
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
-                checkGLcall("glDisable(GL_TEXTURE_2D)");
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
-                checkGLcall("glDisable(GL_TEXTURE_3D)");
-                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)");
-                }
-                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_glEnable(GL_TEXTURE_1D);
-                checkGLcall("glEnable(GL_TEXTURE_1D)");
-                break;
             case GL_TEXTURE_2D:
             case GL_TEXTURE_2D:
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D);
-                checkGLcall("glDisable(GL_TEXTURE_1D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
                 checkGLcall("glDisable(GL_TEXTURE_3D)");
                 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
                 checkGLcall("glDisable(GL_TEXTURE_3D)");
                 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
@@ -6130,8 +6055,6 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st
                 checkGLcall("glEnable(GL_TEXTURE_2D)");
                 break;
             case GL_TEXTURE_RECTANGLE_ARB:
                 checkGLcall("glEnable(GL_TEXTURE_2D)");
                 break;
             case GL_TEXTURE_RECTANGLE_ARB:
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D);
-                checkGLcall("glDisable(GL_TEXTURE_1D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
@@ -6155,16 +6078,12 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st
                     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_RECTANGLE_ARB);
                     checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
                 }
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D);
-                checkGLcall("glDisable(GL_TEXTURE_1D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
                 checkGLcall("glEnable(GL_TEXTURE_3D)");
                 break;
             case GL_TEXTURE_CUBE_MAP_ARB:
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
                 checkGLcall("glEnable(GL_TEXTURE_3D)");
                 break;
             case GL_TEXTURE_CUBE_MAP_ARB:
-                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D);
-                checkGLcall("glDisable(GL_TEXTURE_1D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
                 checkGLcall("glDisable(GL_TEXTURE_2D)");
                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
@@ -6181,8 +6100,6 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st
     }
     else
     {
     }
     else
     {
-        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D);
-        checkGLcall("glDisable(GL_TEXTURE_1D)");
         gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
         checkGLcall("glEnable(GL_TEXTURE_2D)");
         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
         gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
         checkGLcall("glEnable(GL_TEXTURE_2D)");
         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
index bed39db..5edaef8 100644 (file)
@@ -48,11 +48,6 @@ static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
         {GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_RECTANGLE},
         {GL_TEXTURE_3D,        0, GL_TEXTURE_3D},
 
         {GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_RECTANGLE},
         {GL_TEXTURE_3D,        0, GL_TEXTURE_3D},
 
-        {GL_TEXTURE_1D,       0,                          GL_TEXTURE_1D},
-        {GL_TEXTURE_1D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
-        {GL_TEXTURE_1D_ARRAY, 0,                          GL_TEXTURE_1D},
-        {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
-
         {GL_TEXTURE_2D,       0,                          GL_TEXTURE_2D},
         {GL_TEXTURE_2D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
         {GL_TEXTURE_2D_ARRAY, 0,                          GL_TEXTURE_2D},
         {GL_TEXTURE_2D,       0,                          GL_TEXTURE_2D},
         {GL_TEXTURE_2D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
         {GL_TEXTURE_2D_ARRAY, 0,                          GL_TEXTURE_2D},
@@ -64,6 +59,11 @@ static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info,
         {GL_TEXTURE_2D_MULTISAMPLE,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
         {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0,                          GL_TEXTURE_2D_MULTISAMPLE},
         {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
         {GL_TEXTURE_2D_MULTISAMPLE,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
         {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0,                          GL_TEXTURE_2D_MULTISAMPLE},
         {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
+
+        {GL_TEXTURE_1D,       0,                          GL_TEXTURE_1D},
+        {GL_TEXTURE_1D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
+        {GL_TEXTURE_1D_ARRAY, 0,                          GL_TEXTURE_1D},
+        {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
     };
     unsigned int i;
 
     };
     unsigned int i;
 
@@ -750,10 +750,8 @@ static void wined3d_shader_resource_view_cs_init(void *object)
                     debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
         }
     }
                     debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
         }
     }
-#if defined(STAGING_CSMT)
 
     wined3d_resource_release(resource);
 
     wined3d_resource_release(resource);
-#endif /* STAGING_CSMT */
 }
 
 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
 }
 
 static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
@@ -770,9 +768,7 @@ static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_
 
     wined3d_resource_incref(view->resource = resource);
 
 
     wined3d_resource_incref(view->resource = resource);
 
-#if defined(STAGING_CSMT)
     wined3d_resource_acquire(resource);
     wined3d_resource_acquire(resource);
-#endif /* STAGING_CSMT */
     wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_cs_init, view);
 
     return WINED3D_OK;
     wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_cs_init, view);
 
     return WINED3D_OK;
@@ -1125,10 +1121,8 @@ static void wined3d_unordered_access_view_cs_init(void *object)
                     desc, texture, view->format);
         }
     }
                     desc, texture, view->format);
         }
     }
-#if defined(STAGING_CSMT)
 
     wined3d_resource_release(resource);
 
     wined3d_resource_release(resource);
-#endif /* STAGING_CSMT */
 }
 
 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
 }
 
 static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
@@ -1145,9 +1139,7 @@ static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_acces
 
     wined3d_resource_incref(view->resource = resource);
 
 
     wined3d_resource_incref(view->resource = resource);
 
-#if defined(STAGING_CSMT)
     wined3d_resource_acquire(resource);
     wined3d_resource_acquire(resource);
-#endif /* STAGING_CSMT */
     wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_cs_init, view);
 
     return WINED3D_OK;
     wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_cs_init, view);
 
     return WINED3D_OK;
index 3022e20..449d987 100644 (file)
@@ -40,7 +40,7 @@
 @ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr long ptr float long)
 @ cdecl wined3d_device_clear_unordered_access_view_uint(ptr ptr ptr)
 @ cdecl wined3d_device_copy_resource(ptr ptr ptr)
 @ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr long ptr float long)
 @ cdecl wined3d_device_clear_unordered_access_view_uint(ptr ptr ptr)
 @ cdecl wined3d_device_copy_resource(ptr ptr ptr)
-@ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr)
+@ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr long)
 @ cdecl wined3d_device_copy_uav_counter(ptr ptr long ptr)
 @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr)
 @ cdecl wined3d_device_decref(ptr)
 @ cdecl wined3d_device_copy_uav_counter(ptr ptr long ptr)
 @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr)
 @ cdecl wined3d_device_decref(ptr)
@@ -86,6 +86,7 @@
 @ cdecl wined3d_device_get_light(ptr long ptr)
 @ cdecl wined3d_device_get_light_enable(ptr long ptr)
 @ cdecl wined3d_device_get_material(ptr ptr)
 @ cdecl wined3d_device_get_light(ptr long ptr)
 @ cdecl wined3d_device_get_light_enable(ptr long ptr)
 @ cdecl wined3d_device_get_material(ptr ptr)
+@ cdecl wined3d_device_get_max_frame_latency(ptr)
 @ cdecl wined3d_device_get_npatch_mode(ptr)
 @ cdecl wined3d_device_get_pixel_shader(ptr)
 @ cdecl wined3d_device_get_predication(ptr ptr)
 @ cdecl wined3d_device_get_npatch_mode(ptr)
 @ cdecl wined3d_device_get_pixel_shader(ptr)
 @ cdecl wined3d_device_get_predication(ptr ptr)
 @ cdecl wined3d_device_get_render_state(ptr long)
 @ cdecl wined3d_device_get_rendertarget_view(ptr long)
 @ cdecl wined3d_device_get_sampler_state(ptr long long)
 @ cdecl wined3d_device_get_render_state(ptr long)
 @ cdecl wined3d_device_get_rendertarget_view(ptr long)
 @ cdecl wined3d_device_get_sampler_state(ptr long long)
-@ cdecl wined3d_device_get_scissor_rect(ptr ptr)
+@ cdecl wined3d_device_get_scissor_rects(ptr ptr ptr)
 @ cdecl wined3d_device_get_software_vertex_processing(ptr)
 @ cdecl wined3d_device_get_stream_output(ptr long ptr)
 @ cdecl wined3d_device_get_stream_source(ptr long ptr ptr ptr)
 @ cdecl wined3d_device_get_software_vertex_processing(ptr)
 @ cdecl wined3d_device_get_stream_output(ptr long ptr)
 @ cdecl wined3d_device_get_stream_source(ptr long ptr ptr ptr)
 @ cdecl wined3d_device_get_unordered_access_view(ptr long)
 @ cdecl wined3d_device_get_vertex_declaration(ptr)
 @ cdecl wined3d_device_get_vertex_shader(ptr)
 @ cdecl wined3d_device_get_unordered_access_view(ptr long)
 @ cdecl wined3d_device_get_vertex_declaration(ptr)
 @ cdecl wined3d_device_get_vertex_shader(ptr)
-@ cdecl wined3d_device_get_viewport(ptr ptr)
+@ cdecl wined3d_device_get_viewports(ptr ptr ptr)
 @ cdecl wined3d_device_get_vs_cb(ptr long)
 @ cdecl wined3d_device_get_vs_consts_b(ptr long long ptr)
 @ cdecl wined3d_device_get_vs_consts_f(ptr long long ptr)
 @ cdecl wined3d_device_get_vs_cb(ptr long)
 @ cdecl wined3d_device_get_vs_consts_b(ptr long long ptr)
 @ cdecl wined3d_device_get_vs_consts_f(ptr long long ptr)
 @ cdecl wined3d_device_set_light(ptr long ptr)
 @ cdecl wined3d_device_set_light_enable(ptr long long)
 @ cdecl wined3d_device_set_material(ptr ptr)
 @ cdecl wined3d_device_set_light(ptr long ptr)
 @ cdecl wined3d_device_set_light_enable(ptr long long)
 @ cdecl wined3d_device_set_material(ptr ptr)
+@ cdecl wined3d_device_set_max_frame_latency(ptr long)
 @ cdecl wined3d_device_set_multithreaded(ptr)
 @ cdecl wined3d_device_set_npatch_mode(ptr float)
 @ cdecl wined3d_device_set_pixel_shader(ptr ptr)
 @ cdecl wined3d_device_set_multithreaded(ptr)
 @ cdecl wined3d_device_set_npatch_mode(ptr float)
 @ cdecl wined3d_device_set_pixel_shader(ptr ptr)
 @ cdecl wined3d_device_set_render_state(ptr long long)
 @ cdecl wined3d_device_set_rendertarget_view(ptr long ptr long)
 @ cdecl wined3d_device_set_sampler_state(ptr long long long)
 @ cdecl wined3d_device_set_render_state(ptr long long)
 @ cdecl wined3d_device_set_rendertarget_view(ptr long ptr long)
 @ cdecl wined3d_device_set_sampler_state(ptr long long long)
-@ cdecl wined3d_device_set_scissor_rect(ptr ptr)
+@ cdecl wined3d_device_set_scissor_rects(ptr long ptr)
 @ cdecl wined3d_device_set_software_vertex_processing(ptr long)
 @ cdecl wined3d_device_set_stream_output(ptr long ptr long)
 @ cdecl wined3d_device_set_stream_source(ptr long ptr long long)
 @ cdecl wined3d_device_set_software_vertex_processing(ptr long)
 @ cdecl wined3d_device_set_stream_output(ptr long ptr long)
 @ cdecl wined3d_device_set_stream_source(ptr long ptr long long)
 @ cdecl wined3d_device_set_unordered_access_view(ptr long ptr long)
 @ cdecl wined3d_device_set_vertex_declaration(ptr ptr)
 @ cdecl wined3d_device_set_vertex_shader(ptr ptr)
 @ cdecl wined3d_device_set_unordered_access_view(ptr long ptr long)
 @ cdecl wined3d_device_set_vertex_declaration(ptr ptr)
 @ cdecl wined3d_device_set_vertex_shader(ptr ptr)
-@ cdecl wined3d_device_set_viewport(ptr ptr)
+@ cdecl wined3d_device_set_viewports(ptr long ptr)
 @ cdecl wined3d_device_set_vs_cb(ptr long ptr)
 @ cdecl wined3d_device_set_vs_consts_b(ptr long long ptr)
 @ cdecl wined3d_device_set_vs_consts_f(ptr long long ptr)
 @ cdecl wined3d_device_set_vs_cb(ptr long ptr)
 @ cdecl wined3d_device_set_vs_consts_b(ptr long long ptr)
 @ cdecl wined3d_device_set_vs_consts_f(ptr long long ptr)
 @ cdecl wined3d_device_show_cursor(ptr long)
 @ cdecl wined3d_device_uninit_3d(ptr)
 @ cdecl wined3d_device_uninit_gdi(ptr)
 @ cdecl wined3d_device_show_cursor(ptr long)
 @ cdecl wined3d_device_uninit_3d(ptr)
 @ cdecl wined3d_device_uninit_gdi(ptr)
-@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long)
+@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long long)
 @ cdecl wined3d_device_update_texture(ptr ptr ptr)
 @ cdecl wined3d_device_validate_device(ptr ptr)
 
 @ cdecl wined3d_device_update_texture(ptr ptr ptr)
 @ cdecl wined3d_device_validate_device(ptr ptr)
 
 @ cdecl wined3d_stateblock_decref(ptr)
 @ cdecl wined3d_stateblock_incref(ptr)
 
 @ cdecl wined3d_stateblock_decref(ptr)
 @ cdecl wined3d_stateblock_incref(ptr)
 
-@ cdecl wined3d_strictdrawing_set(long)
-
 @ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_swapchain_decref(ptr)
 @ cdecl wined3d_swapchain_get_back_buffer(ptr long)
 @ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_swapchain_decref(ptr)
 @ cdecl wined3d_swapchain_get_back_buffer(ptr long)
index 87283c8..14f8a49 100644 (file)
@@ -89,6 +89,7 @@ enum wined3d_gl_extension
     ARB_POINT_PARAMETERS,
     ARB_POINT_SPRITE,
     ARB_PROVOKING_VERTEX,
     ARB_POINT_PARAMETERS,
     ARB_POINT_SPRITE,
     ARB_PROVOKING_VERTEX,
+    ARB_SAMPLE_SHADING,
     ARB_SAMPLER_OBJECTS,
     ARB_SEAMLESS_CUBE_MAP,
     ARB_SHADER_ATOMIC_COUNTERS,
     ARB_SAMPLER_OBJECTS,
     ARB_SEAMLESS_CUBE_MAP,
     ARB_SHADER_ATOMIC_COUNTERS,
@@ -96,6 +97,7 @@ enum wined3d_gl_extension
     ARB_SHADER_IMAGE_LOAD_STORE,
     ARB_SHADER_IMAGE_SIZE,
     ARB_SHADER_STORAGE_BUFFER_OBJECT,
     ARB_SHADER_IMAGE_LOAD_STORE,
     ARB_SHADER_IMAGE_SIZE,
     ARB_SHADER_STORAGE_BUFFER_OBJECT,
+    ARB_SHADER_TEXTURE_IMAGE_SAMPLES,
     ARB_SHADER_TEXTURE_LOD,
     ARB_SHADING_LANGUAGE_100,
     ARB_SHADING_LANGUAGE_420PACK,
     ARB_SHADER_TEXTURE_LOD,
     ARB_SHADING_LANGUAGE_100,
     ARB_SHADING_LANGUAGE_420PACK,
@@ -134,7 +136,6 @@ enum wined3d_gl_extension
     ARB_TRANSFORM_FEEDBACK3,
     ARB_UNIFORM_BUFFER_OBJECT,
     ARB_VERTEX_ARRAY_BGRA,
     ARB_TRANSFORM_FEEDBACK3,
     ARB_UNIFORM_BUFFER_OBJECT,
     ARB_VERTEX_ARRAY_BGRA,
-    ARB_VERTEX_BLEND,
     ARB_VERTEX_BUFFER_OBJECT,
     ARB_VERTEX_PROGRAM,
     ARB_VERTEX_SHADER,
     ARB_VERTEX_BUFFER_OBJECT,
     ARB_VERTEX_PROGRAM,
     ARB_VERTEX_SHADER,
index 28e6fe6..604e6e4 100644 (file)
@@ -74,7 +74,7 @@ struct wined3d_settings wined3d_settings =
 {
     TRUE,           /* Multithreaded CS by default. */
     FALSE,          /* explicit_gl_version */
 {
     TRUE,           /* Multithreaded CS by default. */
     FALSE,          /* explicit_gl_version */
-    MAKEDWORD_VERSION(1, 0), /* Default to legacy OpenGL */
+    MAKEDWORD_VERSION(4, 4), /* Default to OpenGL 4.4 */
     TRUE,           /* Use of GLSL enabled by default */
     ORM_FBO,        /* Use FBOs to do offscreen rendering */
     PCI_VENDOR_NONE,/* PCI Vendor ID */
     TRUE,           /* Use of GLSL enabled by default */
     ORM_FBO,        /* Use FBOs to do offscreen rendering */
     PCI_VENDOR_NONE,/* PCI Vendor ID */
@@ -83,7 +83,6 @@ struct wined3d_settings wined3d_settings =
     NULL,           /* No wine logo by default */
     TRUE,           /* Prefer multisample textures to multisample renderbuffers. */
     ~0u,            /* Don't force a specific sample count by default. */
     NULL,           /* No wine logo by default */
     TRUE,           /* Prefer multisample textures to multisample renderbuffers. */
     ~0u,            /* Don't force a specific sample count by default. */
-    FALSE,          /* No strict draw ordering. */
     FALSE,          /* Don't range check relative addressing indices in float constants. */
     ~0U,            /* No VS shader model limit by default. */
     ~0U,            /* No HS shader model limit by default. */
     FALSE,          /* Don't range check relative addressing indices in float constants. */
     ~0U,            /* No VS shader model limit by default. */
     ~0U,            /* No HS shader model limit by default. */
@@ -290,13 +289,6 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
         if (!get_config_key_dword(hkey, appkey, "SampleCount", &wined3d_settings.sample_count))
             ERR_(winediag)("Forcing sample count to %u. This may not be compatible with all applications.\n",
                     wined3d_settings.sample_count);
         if (!get_config_key_dword(hkey, appkey, "SampleCount", &wined3d_settings.sample_count))
             ERR_(winediag)("Forcing sample count to %u. This may not be compatible with all applications.\n",
                     wined3d_settings.sample_count);
-        if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size)
-                && !strcmp(buffer,"enabled"))
-        {
-            ERR_(winediag)("\"StrictDrawOrdering\" is deprecated, please use \"csmt\" instead.\n");
-            TRACE("Enforcing strict draw ordering.\n");
-            wined3d_settings.strict_draw_ordering = TRUE;
-        }
         if (!get_config_key(hkey, appkey, "CheckFloatConstants", buffer, size)
                 && !strcmp(buffer, "enabled"))
         {
         if (!get_config_key(hkey, appkey, "CheckFloatConstants", buffer, size)
                 && !strcmp(buffer, "enabled"))
         {
@@ -516,11 +508,6 @@ void wined3d_unregister_window(HWND window)
     wined3d_wndproc_mutex_unlock();
 }
 
     wined3d_wndproc_mutex_unlock();
 }
 
-void CDECL wined3d_strictdrawing_set(int value)
-{
-    wined3d_settings.strict_draw_ordering = value;
-}
-
 /* At process attach */
 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
 /* At process attach */
 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
index 878a4d0..7b3731c 100644 (file)
@@ -277,7 +277,6 @@ static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup
 #define MAX_TGSM_REGISTERS          8192
 #define MAX_VERTEX_BLENDS           4
 #define MAX_VERTEX_INDEX_BLENDS     9
 #define MAX_TGSM_REGISTERS          8192
 #define MAX_VERTEX_BLENDS           4
 #define MAX_VERTEX_INDEX_BLENDS     9
-#define MAX_MULTISAMPLE_TYPES       8
 #define MAX_RENDER_TARGETS          8
 
 struct min_lookup
 #define MAX_RENDER_TARGETS          8
 
 struct min_lookup
@@ -398,7 +397,6 @@ struct wined3d_settings
     char *logo;
     unsigned int multisample_textures;
     unsigned int sample_count;
     char *logo;
     unsigned int multisample_textures;
     unsigned int sample_count;
-    BOOL strict_draw_ordering;
     BOOL check_float_constants;
     unsigned int max_sm_vs;
     unsigned int max_sm_hs;
     BOOL check_float_constants;
     unsigned int max_sm_vs;
     unsigned int max_sm_hs;
@@ -502,6 +500,7 @@ enum wined3d_shader_register_type
     WINED3DSPR_GSINSTID,
     WINED3DSPR_DEPTHOUTGE,
     WINED3DSPR_DEPTHOUTLE,
     WINED3DSPR_GSINSTID,
     WINED3DSPR_DEPTHOUTGE,
     WINED3DSPR_DEPTHOUTLE,
+    WINED3DSPR_RASTERIZER,
 };
 
 enum wined3d_data_type
 };
 
 enum wined3d_data_type
@@ -623,6 +622,14 @@ enum wined3d_tessellator_partitioning
 #define WINED3DSI_SAMPLE_INFO_UINT  0x1
 #define WINED3DSI_SAMPLER_COMPARISON_MODE 0x1
 
 #define WINED3DSI_SAMPLE_INFO_UINT  0x1
 #define WINED3DSI_SAMPLER_COMPARISON_MODE 0x1
 
+#define WINED3DSI_PRECISE_X         0x100
+#define WINED3DSI_PRECISE_Y         0x200
+#define WINED3DSI_PRECISE_Z         0x400
+#define WINED3DSI_PRECISE_W         0x800
+#define WINED3DSI_PRECISE_XYZW      (WINED3DSI_PRECISE_X | WINED3DSI_PRECISE_Y \
+                                    | WINED3DSI_PRECISE_Z | WINED3DSI_PRECISE_W)
+#define WINED3DSI_PRECISE_SHIFT     8
+
 enum wined3d_shader_rel_op
 {
     WINED3D_SHADER_REL_OP_GT = 1,
 enum wined3d_shader_rel_op
 {
     WINED3D_SHADER_REL_OP_GT = 1,
@@ -934,6 +941,7 @@ enum wined3d_shader_type
 
     WINED3D_SHADER_TYPE_COMPUTE = WINED3D_SHADER_TYPE_GRAPHICS_COUNT,
     WINED3D_SHADER_TYPE_COUNT,
 
     WINED3D_SHADER_TYPE_COMPUTE = WINED3D_SHADER_TYPE_GRAPHICS_COUNT,
     WINED3D_SHADER_TYPE_COUNT,
+    WINED3D_SHADER_TYPE_INVALID = WINED3D_SHADER_TYPE_COUNT,
 };
 
 struct wined3d_shader_version
 };
 
 struct wined3d_shader_version
@@ -1034,7 +1042,9 @@ struct wined3d_shader_reg_maps
     DWORD point_size     : 1;
     DWORD vocp           : 1;
     DWORD input_rel_addressing : 1;
     DWORD point_size     : 1;
     DWORD vocp           : 1;
     DWORD input_rel_addressing : 1;
-    DWORD padding        : 16;
+    DWORD viewport_array : 1;
+    DWORD sample_mask    : 1;
+    DWORD padding        : 14;
 
     DWORD rt_mask; /* Used render targets, 32 max. */
 
 
     DWORD rt_mask; /* Used render targets, 32 max. */
 
@@ -1270,6 +1280,9 @@ struct wined3d_shader_frontend
 extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN;
 extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN;
 
 extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN;
 extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN;
 
+enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code,
+        size_t byte_code_size) DECLSPEC_HIDDEN;
+
 typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *);
 
 #define WINED3D_SHADER_CAP_VS_CLIPPING      0x00000001
 typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *);
 
 #define WINED3D_SHADER_CAP_VS_CLIPPING      0x00000001
@@ -1305,10 +1318,11 @@ enum wined3d_gl_resource_type
     WINED3D_GL_RES_TYPE_COUNT           = 7,
 };
 
     WINED3D_GL_RES_TYPE_COUNT           = 7,
 };
 
-enum vertexprocessing_mode {
-    fixedfunction,
-    vertexshader,
-    pretransformed
+enum wined3d_vertex_processing_mode
+{
+    WINED3D_VP_MODE_FF,
+    WINED3D_VP_MODE_SHADER,
+    WINED3D_VP_MODE_NONE,
 };
 
 #define WINED3D_CONST_NUM_UNUSED ~0U
 };
 
 #define WINED3D_CONST_NUM_UNUSED ~0U
@@ -1343,7 +1357,7 @@ enum wined3d_shader_tex_types
 struct ps_compile_args
 {
     struct color_fixup_desc     color_fixup[MAX_FRAGMENT_SAMPLERS];
 struct ps_compile_args
 {
     struct color_fixup_desc     color_fixup[MAX_FRAGMENT_SAMPLERS];
-    enum vertexprocessing_mode  vp_mode;
+    enum wined3d_vertex_processing_mode vp_mode;
     enum wined3d_ffp_ps_fog_mode fog;
     WORD                        tex_transform; /* ps 1.0-1.3, 4 textures */
     WORD                        tex_types; /* ps 1.0 - 1.4, 6 textures */
     enum wined3d_ffp_ps_fog_mode fog;
     WORD                        tex_transform; /* ps 1.0-1.3, 4 textures */
     WORD                        tex_types; /* ps 1.0 - 1.4, 6 textures */
@@ -1396,6 +1410,7 @@ struct ds_compile_args
 struct gs_compile_args
 {
     unsigned int output_count;
 struct gs_compile_args
 {
     unsigned int output_count;
+    enum wined3d_primitive_type primitive_type;
     DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE];
 };
 
     DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE];
 };
 
@@ -1629,10 +1644,10 @@ enum wined3d_pipeline
 #define STATE_MATERIAL (STATE_CLIPPLANE(MAX_CLIP_DISTANCES))
 #define STATE_IS_MATERIAL(a) ((a) == STATE_MATERIAL)
 
 #define STATE_MATERIAL (STATE_CLIPPLANE(MAX_CLIP_DISTANCES))
 #define STATE_IS_MATERIAL(a) ((a) == STATE_MATERIAL)
 
-#define STATE_FRONTFACE (STATE_MATERIAL + 1)
-#define STATE_IS_FRONTFACE(a) ((a) == STATE_FRONTFACE)
+#define STATE_RASTERIZER (STATE_MATERIAL + 1)
+#define STATE_IS_RASTERIZER(a) ((a) == STATE_RASTERIZER)
 
 
-#define STATE_POINTSPRITECOORDORIGIN  (STATE_FRONTFACE + 1)
+#define STATE_POINTSPRITECOORDORIGIN (STATE_RASTERIZER + 1)
 #define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN)
 
 #define STATE_BASEVERTEXINDEX  (STATE_POINTSPRITECOORDORIGIN + 1)
 #define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN)
 
 #define STATE_BASEVERTEXINDEX  (STATE_POINTSPRITECOORDORIGIN + 1)
@@ -1888,7 +1903,7 @@ struct wined3d_context
     DWORD last_was_vshader : 1;
     DWORD last_was_normal : 1;
     DWORD namedArraysLoaded : 1;
     DWORD last_was_vshader : 1;
     DWORD last_was_normal : 1;
     DWORD namedArraysLoaded : 1;
-    DWORD numberedArraysLoaded : 1;
+    DWORD last_was_ffp_blit : 1;
     DWORD last_was_blit : 1;
     DWORD last_was_ckey : 1;
     DWORD fog_coord : 1;
     DWORD last_was_blit : 1;
     DWORD last_was_ckey : 1;
     DWORD fog_coord : 1;
@@ -1897,6 +1912,7 @@ struct wined3d_context
     DWORD current : 1;
     DWORD destroyed : 1;
     DWORD valid : 1;
     DWORD current : 1;
     DWORD destroyed : 1;
     DWORD valid : 1;
+
     DWORD texShaderBumpMap : 8;         /* MAX_TEXTURES, 8 */
     DWORD lastWasPow2Texture : 8;       /* MAX_TEXTURES, 8 */
     DWORD fixed_function_usage_map : 8; /* MAX_TEXTURES, 8 */
     DWORD texShaderBumpMap : 8;         /* MAX_TEXTURES, 8 */
     DWORD lastWasPow2Texture : 8;       /* MAX_TEXTURES, 8 */
     DWORD fixed_function_usage_map : 8; /* MAX_TEXTURES, 8 */
@@ -1905,6 +1921,7 @@ struct wined3d_context
     DWORD rebind_fbo : 1;
     DWORD needs_set : 1;
     DWORD hdc_is_private : 1;
     DWORD rebind_fbo : 1;
     DWORD needs_set : 1;
     DWORD hdc_is_private : 1;
+
     DWORD hdc_has_format : 1;           /* only meaningful if hdc_is_private */
     DWORD update_shader_resource_bindings : 1;
     DWORD update_compute_shader_resource_bindings : 1;
     DWORD hdc_has_format : 1;           /* only meaningful if hdc_is_private */
     DWORD update_shader_resource_bindings : 1;
     DWORD update_compute_shader_resource_bindings : 1;
@@ -1918,8 +1935,9 @@ struct wined3d_context
     DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */
     DWORD last_was_dual_blend : 1;
     DWORD padding : 8;
     DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */
     DWORD last_was_dual_blend : 1;
     DWORD padding : 8;
+
     DWORD constant_update_mask;
     DWORD constant_update_mask;
-    DWORD                   numbered_array_mask;
+    DWORD numbered_array_mask;
     GLenum                  tracking_parm;     /* Which source is tracking current colour         */
     GLenum                  untracked_materials[2];
     UINT                    blit_w, blit_h;
     GLenum                  tracking_parm;     /* Which source is tracking current colour         */
     GLenum                  untracked_materials[2];
     UINT                    blit_w, blit_h;
@@ -1986,6 +2004,8 @@ struct wined3d_context
     struct wined3d_fence *buffer_fences[MAX_ATTRIBS];
     unsigned int buffer_fence_count;
 
     struct wined3d_fence *buffer_fences[MAX_ATTRIBS];
     unsigned int buffer_fence_count;
 
+    GLuint blit_vbo;
+
     DWORD tex_unit_map[MAX_COMBINED_SAMPLERS];
     DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS];
 
     DWORD tex_unit_map[MAX_COMBINED_SAMPLERS];
     DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS];
 
@@ -1994,6 +2014,9 @@ struct wined3d_context
     GLfloat                 fog_coord_value;
     GLfloat                 color[4], fogstart, fogend, fogcolor[4];
     GLuint                  dummy_arbfp_prog;
     GLfloat                 fog_coord_value;
     GLfloat                 color[4], fogstart, fogend, fogcolor[4];
     GLuint                  dummy_arbfp_prog;
+
+    unsigned int viewport_count;
+    unsigned int scissor_rect_count;
 };
 
 struct wined3d_fb_state
 };
 
 struct wined3d_fb_state
@@ -2089,8 +2112,6 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_
         const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
         const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN;
 
         const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
         const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN;
 
-struct wined3d_surface;
-
 enum wined3d_blit_op
 {
     WINED3D_BLIT_OP_COLOR_BLIT,
 enum wined3d_blit_op
 {
     WINED3D_BLIT_OP_COLOR_BLIT,
@@ -2115,9 +2136,10 @@ struct wined3d_blitter_ops
             unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
             const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil);
     DWORD (*blitter_blit)(struct wined3d_blitter *blitter, enum wined3d_blit_op op, struct wined3d_context *context,
             unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
             const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil);
     DWORD (*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,
-            const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter);
+            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 *colour_key,
+            enum wined3d_texture_filter_type filter);
 };
 
 void wined3d_arbfp_blitter_create(struct wined3d_blitter **next,
 };
 
 void wined3d_arbfp_blitter_create(struct wined3d_blitter **next,
@@ -2127,6 +2149,8 @@ void wined3d_fbo_blitter_create(struct wined3d_blitter **next,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_ffp_blitter_create(struct wined3d_blitter **next,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_ffp_blitter_create(struct wined3d_blitter **next,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+struct wined3d_blitter *wined3d_glsl_blitter_create(struct wined3d_blitter **next,
+        const struct wined3d_device *device) DECLSPEC_HIDDEN;
 void wined3d_raw_blitter_create(struct wined3d_blitter **next,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 
 void wined3d_raw_blitter_create(struct wined3d_blitter **next,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 
@@ -2141,7 +2165,10 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
 BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state,
         UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN;
 void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
 BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state,
         UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN;
 void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
-        struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN;
+        struct wined3d_resource *rt, unsigned int rt_sub_resource_idx,
+        struct wined3d_resource *ds, unsigned int ds_sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
+void context_apply_ffp_blit_state(struct wined3d_context *context,
+        const struct wined3d_device *device) DECLSPEC_HIDDEN;
 void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info,
         unsigned int unit) DECLSPEC_HIDDEN;
 void context_bind_bo(struct wined3d_context *context, GLenum binding, GLuint name) DECLSPEC_HIDDEN;
 void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info,
         unsigned int unit) DECLSPEC_HIDDEN;
 void context_bind_bo(struct wined3d_context *context, GLenum binding, GLuint name) DECLSPEC_HIDDEN;
@@ -2156,6 +2183,12 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, stru
         const struct wined3d_format *ds_format) DECLSPEC_HIDDEN;
 HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN;
 void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
         const struct wined3d_format *ds_format) DECLSPEC_HIDDEN;
 HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN;
 void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
+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) DECLSPEC_HIDDEN;
+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) DECLSPEC_HIDDEN;
 void context_enable_clip_distances(struct wined3d_context *context, unsigned int mask) DECLSPEC_HIDDEN;
 void context_end_transform_feedback(struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN;
 void context_enable_clip_distances(struct wined3d_context *context, unsigned int mask) DECLSPEC_HIDDEN;
 void context_end_transform_feedback(struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN;
@@ -2169,14 +2202,16 @@ void context_gl_resource_released(struct wined3d_device *device,
         GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN;
 void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
 void context_invalidate_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
         GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN;
 void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
 void context_invalidate_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
+void context_load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si,
+        GLuint *current_bo, const struct wined3d_state *state) DECLSPEC_HIDDEN;
 void *context_map_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data,
         size_t size, GLenum binding, DWORD flags) DECLSPEC_HIDDEN;
 struct wined3d_context *context_reacquire(const struct wined3d_device *device,
         struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN;
 void *context_map_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data,
         size_t size, GLenum binding, DWORD flags) DECLSPEC_HIDDEN;
 struct wined3d_context *context_reacquire(const struct wined3d_device *device,
         struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN;
-void context_resource_released(const struct wined3d_device *device,
-        struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
-void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) DECLSPEC_HIDDEN;
+void context_resource_released(const struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void context_restore(struct wined3d_context *context, struct wined3d_texture *texture,
+        unsigned int sub_resource_idx) DECLSPEC_HIDDEN;
 BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
 void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
 BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
 void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
@@ -2184,9 +2219,12 @@ void context_state_drawbuf(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 void context_state_fb(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 void context_state_fb(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
-void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+void context_texture_update(struct wined3d_context *context, const struct wined3d_texture *texture) DECLSPEC_HIDDEN;
+void context_unload_tex_coords(const struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_unmap_bo_address(struct wined3d_context *context,
         const struct wined3d_bo_address *data, GLenum binding) DECLSPEC_HIDDEN;
 void context_unmap_bo_address(struct wined3d_context *context,
         const struct wined3d_bo_address *data, GLenum binding) DECLSPEC_HIDDEN;
+void context_update_stream_sources(struct wined3d_context *context,
+        const struct wined3d_state *state) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * Internal representation of a light
 
 /*****************************************************************************
  * Internal representation of a light
@@ -2401,11 +2439,13 @@ enum wined3d_pci_device
     CARD_NVIDIA_GEFORCE_GTX980      = 0x13c0,
     CARD_NVIDIA_GEFORCE_GTX980TI    = 0x17c8,
     CARD_NVIDIA_GEFORCE_GTX1050     = 0x1c81,
     CARD_NVIDIA_GEFORCE_GTX980      = 0x13c0,
     CARD_NVIDIA_GEFORCE_GTX980TI    = 0x17c8,
     CARD_NVIDIA_GEFORCE_GTX1050     = 0x1c81,
+    CARD_NVIDIA_GEFORCE_GTX1050TI   = 0x1c82,
     CARD_NVIDIA_GEFORCE_GTX1060     = 0x1c03,
     CARD_NVIDIA_GEFORCE_GTX1070     = 0x1b81,
     CARD_NVIDIA_GEFORCE_GTX1080     = 0x1b80,
     CARD_NVIDIA_GEFORCE_GTX1080TI   = 0x1b06,
     CARD_NVIDIA_TITANX_PASCAL       = 0x1b00,
     CARD_NVIDIA_GEFORCE_GTX1060     = 0x1c03,
     CARD_NVIDIA_GEFORCE_GTX1070     = 0x1b81,
     CARD_NVIDIA_GEFORCE_GTX1080     = 0x1b80,
     CARD_NVIDIA_GEFORCE_GTX1080TI   = 0x1b06,
     CARD_NVIDIA_TITANX_PASCAL       = 0x1b00,
+    CARD_NVIDIA_TITANV              = 0x1d81,
 
     CARD_VMWARE_SVGA3D              = 0x0405,
 
 
     CARD_VMWARE_SVGA3D              = 0x0405,
 
@@ -2533,7 +2573,6 @@ struct wined3d_gl_limits
     UINT texture3d_size;
     float pointsize_max;
     float pointsize_min;
     UINT texture3d_size;
     float pointsize_max;
     float pointsize_min;
-    UINT blends;
     UINT anisotropy;
     float shininess;
     UINT samples;
     UINT anisotropy;
     float shininess;
     UINT samples;
@@ -2636,17 +2675,11 @@ BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx
 
 void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN;
 
 
 void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN;
 
-enum projection_types
+enum wined3d_projection_type
 {
 {
-    proj_none    = 0,
-    proj_count3  = 1,
-    proj_count4  = 2
-};
-
-enum dst_arg
-{
-    resultreg    = 0,
-    tempreg      = 1
+    WINED3D_PROJECTION_NONE    = 0,
+    WINED3D_PROJECTION_COUNT3  = 1,
+    WINED3D_PROJECTION_COUNT4  = 2
 };
 
 /*****************************************************************************
 };
 
 /*****************************************************************************
@@ -2667,7 +2700,7 @@ struct texture_stage_op
 
     struct color_fixup_desc color_fixup;
     unsigned                tex_type : 3;
 
     struct color_fixup_desc color_fixup;
     unsigned                tex_type : 3;
-    unsigned                dst : 1;
+    unsigned                tmp_dst : 1;
     unsigned                projected : 2;
     unsigned                padding : 10;
 };
     unsigned                projected : 2;
     unsigned                padding : 10;
 };
@@ -2853,8 +2886,10 @@ struct wined3d_state
     struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
     struct wined3d_vec4 clip_planes[MAX_CLIP_DISTANCES];
     struct wined3d_material material;
     struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
     struct wined3d_vec4 clip_planes[MAX_CLIP_DISTANCES];
     struct wined3d_material material;
-    struct wined3d_viewport viewport;
-    RECT scissor_rect;
+    struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS];
+    unsigned int viewport_count;
+    RECT scissor_rects[WINED3D_MAX_VIEWPORTS];
+    unsigned int scissor_rect_count;
 
     /* Light hashmap. Collisions are handled using linked lists. */
 #define LIGHTMAP_SIZE 43
 
     /* Light hashmap. Collisions are handled using linked lists. */
 #define LIGHTMAP_SIZE 43
@@ -2885,29 +2920,19 @@ static inline BOOL wined3d_dualblend_enabled(const struct wined3d_state *state,
 
 struct wined3d_dummy_textures
 {
 
 struct wined3d_dummy_textures
 {
-    GLuint tex_2d;
     GLuint tex_1d;
     GLuint tex_1d;
+    GLuint tex_2d;
     GLuint tex_rect;
     GLuint tex_3d;
     GLuint tex_cube;
     GLuint tex_cube_array;
     GLuint tex_rect;
     GLuint tex_3d;
     GLuint tex_cube;
     GLuint tex_cube_array;
-    GLuint tex_2d_array;
     GLuint tex_1d_array;
     GLuint tex_1d_array;
+    GLuint tex_2d_array;
     GLuint tex_buffer;
     GLuint tex_2d_ms;
     GLuint tex_2d_ms_array;
 };
 
     GLuint tex_buffer;
     GLuint tex_2d_ms;
     GLuint tex_2d_ms_array;
 };
 
-#if defined(STAGING_CSMT)
-struct wined3d_gl_bo
-{
-    GLuint name;
-    GLenum usage;
-    GLenum type_hint;
-    UINT size;
-};
-
-#endif /* STAGING_CSMT */
 #define WINED3D_UNMAPPED_STAGE ~0u
 
 /* Multithreaded flag. Removed from the public header to signal that
 #define WINED3D_UNMAPPED_STAGE ~0u
 
 /* Multithreaded flag. Removed from the public header to signal that
@@ -2936,13 +2961,12 @@ struct wined3d_device
     APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1];
     struct wined3d_blitter *blitter;
 
     APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1];
     struct wined3d_blitter *blitter;
 
-    BYTE vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
     BYTE bCursorVisible : 1;
     BYTE d3d_initialized : 1;
     BYTE inScene : 1;                   /* A flag to check for proper BeginScene / EndScene call pairs */
     BYTE softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
     BYTE filter_messages : 1;
     BYTE bCursorVisible : 1;
     BYTE d3d_initialized : 1;
     BYTE inScene : 1;                   /* A flag to check for proper BeginScene / EndScene call pairs */
     BYTE softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
     BYTE filter_messages : 1;
-    BYTE padding : 2;
+    BYTE padding : 3;
 
     unsigned char           surface_alignment; /* Line Alignment of surfaces                      */
 
 
     unsigned char           surface_alignment; /* Line Alignment of surfaces                      */
 
@@ -2959,6 +2983,7 @@ struct wined3d_device
     struct wined3d_rendertarget_view *back_buffer_view;
     struct wined3d_swapchain **swapchains;
     UINT swapchain_count;
     struct wined3d_rendertarget_view *back_buffer_view;
     struct wined3d_swapchain **swapchains;
     UINT swapchain_count;
+    unsigned int max_frame_latency;
 
     struct list             resources; /* a linked list to track resources created by the device */
     struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
 
     struct list             resources; /* a linked list to track resources created by the device */
     struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
@@ -3008,12 +3033,6 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
-#if defined(STAGING_CSMT)
-struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage,
-        GLenum type_hint, struct wined3d_context *context) DECLSPEC_HIDDEN;
-void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo,
-        const struct wined3d_context *context) DECLSPEC_HIDDEN;
-#endif /* STAGING_CSMT */
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
 {
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
 {
@@ -3119,16 +3138,16 @@ struct gl_texture
     GLuint name;
 };
 
     GLuint name;
 };
 
+struct wined3d_blt_info
+{
+    GLenum bind_target;
+    struct wined3d_vec3 texcoords[4];
+};
+
 struct wined3d_texture_ops
 {
 struct wined3d_texture_ops
 {
-    void (*texture_upload_data)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-            const struct wined3d_context *context, const struct wined3d_box *box,
-            const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch);
     BOOL (*texture_load_location)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
             struct wined3d_context *context, DWORD location);
     BOOL (*texture_load_location)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
             struct wined3d_context *context, DWORD location);
-    void (*texture_prepare_texture)(struct wined3d_texture *texture,
-            struct wined3d_context *context, BOOL srgb);
-    void (*texture_cleanup_sub_resources)(struct wined3d_texture *texture);
 };
 
 #define WINED3D_TEXTURE_COND_NP2            0x00000001
 };
 
 #define WINED3D_TEXTURE_COND_NP2            0x00000001
@@ -3194,30 +3213,32 @@ struct wined3d_texture
     {
         struct list entry;
         struct list overlays;
     {
         struct list entry;
         struct list overlays;
-        struct wined3d_surface *dst;
+        struct wined3d_texture *dst_texture;
+        unsigned int dst_sub_resource_idx;
         RECT src_rect;
         RECT dst_rect;
     } *overlay_info;
 
         RECT src_rect;
         RECT dst_rect;
     } *overlay_info;
 
+    struct wined3d_dc_info
+    {
+        HBITMAP bitmap;
+        HDC dc;
+    } *dc_info;
+
+    struct list renderbuffers;
+    const struct wined3d_renderbuffer_entry *current_renderbuffer;
+
     struct wined3d_texture_sub_resource
     {
         void *parent;
         const struct wined3d_parent_ops *parent_ops;
 
     struct wined3d_texture_sub_resource
     {
         void *parent;
         const struct wined3d_parent_ops *parent_ops;
 
-        union
-        {
-            struct wined3d_surface *surface;
-        } u;
         unsigned int offset;
         unsigned int size;
 
         unsigned int map_count;
         DWORD locations;
         unsigned int offset;
         unsigned int size;
 
         unsigned int map_count;
         DWORD locations;
-#if !defined(STAGING_CSMT)
         GLuint buffer_object;
         GLuint buffer_object;
-#else  /* STAGING_CSMT */
-        struct wined3d_gl_bo *buffer;
-#endif /* STAGING_CSMT */
     } sub_resources[1];
 };
 
     } sub_resources[1];
 };
 
@@ -3279,6 +3300,32 @@ static inline unsigned int wined3d_texture_get_level_pow2_height(const struct wi
     return max(1, texture->pow2_height >> level);
 }
 
     return max(1, texture->pow2_height >> level);
 }
 
+static inline void wined3d_texture_get_level_box(const struct wined3d_texture *texture,
+        unsigned int level, struct wined3d_box *box)
+{
+    wined3d_box_set(box, 0, 0,
+            wined3d_texture_get_level_width(texture, level),
+            wined3d_texture_get_level_height(texture, level),
+            0, wined3d_texture_get_level_depth(texture, level));
+}
+
+HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        const struct wined3d_box *dst_box, struct wined3d_texture *src_texture,
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags,
+        const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
+void texture2d_get_blt_info(const struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        const RECT *rect, struct wined3d_blt_info *info) DECLSPEC_HIDDEN;
+BOOL texture2d_load_drawable(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
+void texture2d_load_fb_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        BOOL srgb, struct wined3d_context *context) DECLSPEC_HIDDEN;
+BOOL texture2d_load_renderbuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD dst_location) DECLSPEC_HIDDEN;
+BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, DWORD dst_location) DECLSPEC_HIDDEN;
+BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx,
+        struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
+
 void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture,
         const struct wined3d_sampler_desc *sampler_desc, const struct wined3d_context *context) DECLSPEC_HIDDEN;
 void wined3d_texture_bind(struct wined3d_texture *texture,
 void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture,
         const struct wined3d_sampler_desc *sampler_desc, const struct wined3d_context *context) DECLSPEC_HIDDEN;
 void wined3d_texture_bind(struct wined3d_texture *texture,
@@ -3300,12 +3347,20 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
+void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
+        unsigned int level, const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
 void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture,
+        HWND window, RECT *rect) DECLSPEC_HIDDEN;
 void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
 void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        const struct wined3d_context *context, const struct wined3d_box *box,
-        const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) DECLSPEC_HIDDEN;
+        struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box,
+        const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) DECLSPEC_HIDDEN;
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN;
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
 
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
 
@@ -3353,49 +3408,6 @@ struct fbo_entry
     } key;
 };
 
     } key;
 };
 
-struct wined3d_surface
-{
-    struct wined3d_texture *container;
-
-    unsigned int texture_level;
-    unsigned int texture_layer;
-
-    /* For GetDC */
-    HBITMAP bitmap;
-    HDC dc;
-
-    struct list               renderbuffers;
-    const struct wined3d_renderbuffer_entry *current_renderbuffer;
-};
-
-static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
-{
-    return surface->texture_layer * surface->container->level_count + surface->texture_level;
-}
-
-static inline struct wined3d_texture_sub_resource *surface_get_sub_resource(struct wined3d_surface *surface)
-{
-    return &surface->container->sub_resources[surface_get_sub_resource_idx(surface)];
-}
-
-HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
-        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
-        const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
-        struct wined3d_context *context) DECLSPEC_HIDDEN;
-BOOL surface_load_location(struct wined3d_surface *surface,
-        struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
-void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
-        const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
-void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN;
-void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
-        const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
-        BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
-
-void draw_textured_quad(struct wined3d_texture *texture, unsigned int sub_resource_idx,
-        struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect,
-        enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-
 struct wined3d_sampler
 {
     struct wine_rb_entry entry;
 struct wined3d_sampler
 {
     struct wine_rb_entry entry;
@@ -3542,9 +3554,7 @@ struct wined3d_cs_queue
 
 struct wined3d_cs_ops
 {
 
 struct wined3d_cs_ops
 {
-#if defined(STAGING_CSMT)
     BOOL (*check_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id);
     BOOL (*check_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id);
-#endif /* STAGING_CSMT */
     void *(*require_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id);
     void (*submit)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id);
     void (*finish)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id);
     void *(*require_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id);
     void (*submit)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id);
     void (*finish)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id);
@@ -3604,7 +3614,7 @@ void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect,
 void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 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) DECLSPEC_HIDDEN;
+        const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) DECLSPEC_HIDDEN;
@@ -3635,7 +3645,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type
         UINT sampler_idx, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
         enum wined3d_sampler_state state, DWORD value) DECLSPEC_HIDDEN;
         UINT sampler_idx, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
         enum wined3d_sampler_state state, DWORD value) DECLSPEC_HIDDEN;
-void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type,
         struct wined3d_shader *shader) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type,
         struct wined3d_shader *shader) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
@@ -3654,7 +3664,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined
         unsigned int initial_count) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
         unsigned int initial_count) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
-void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, const struct wined3d_viewport *viewports) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
 void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
@@ -3762,19 +3772,6 @@ struct wined3d_rendertarget_view
     struct wined3d_view_desc desc;
 };
 
     struct wined3d_view_desc desc;
 };
 
-static inline struct wined3d_surface *wined3d_rendertarget_view_get_surface(
-        const struct wined3d_rendertarget_view *view)
-{
-    struct wined3d_texture *texture;
-
-    if (!view || view->resource->type != WINED3D_RTYPE_TEXTURE_2D)
-        return NULL;
-
-    texture = texture_from_resource(view->resource);
-
-    return texture->sub_resources[view->sub_resource_idx].u.surface;
-}
-
 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
         const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN;
 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view,
 void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view,
         const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN;
 void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view,
@@ -3853,6 +3850,8 @@ struct wined3d_swapchain
     const struct wined3d_format *ds_format;
     struct wined3d_palette *palette;
     RECT front_buffer_update;
     const struct wined3d_format *ds_format;
     struct wined3d_palette *palette;
     RECT front_buffer_update;
+    unsigned int swap_interval;
+    unsigned int max_frame_latency;
 
     LONG prev_time, frames;   /* Performance tracking */
 
 
     LONG prev_time, frames;   /* Performance tracking */
 
@@ -3867,11 +3866,14 @@ struct wined3d_swapchain
 };
 
 void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate) DECLSPEC_HIDDEN;
 };
 
 void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate) DECLSPEC_HIDDEN;
+void wined3d_swapchain_set_swap_interval(struct wined3d_swapchain *swapchain,
+        unsigned int swap_interval) DECLSPEC_HIDDEN;
 struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
-void swapchain_update_swap_interval(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain,
+        const struct wined3d_device *device) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * Utility function prototypes
 
 /*****************************************************************************
  * Utility function prototypes
@@ -3946,6 +3948,7 @@ void state_shademode(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 
 GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN;
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 
 GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN;
+enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) DECLSPEC_HIDDEN;
 
 /* Math utils */
 void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
 
 /* Math utils */
 void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
@@ -4142,13 +4145,14 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
             /* oPos */
             return FALSE;
 
             /* oPos */
             return FALSE;
 
+        case WINED3DSPR_CONSTBOOL:  /* b# */
         case WINED3DSPR_DEPTHOUT:   /* oDepth */
         case WINED3DSPR_DEPTHOUTGE:
         case WINED3DSPR_DEPTHOUTLE:
         case WINED3DSPR_DEPTHOUT:   /* oDepth */
         case WINED3DSPR_DEPTHOUTGE:
         case WINED3DSPR_DEPTHOUTLE:
-        case WINED3DSPR_CONSTBOOL:  /* b# */
         case WINED3DSPR_LOOP:       /* aL */
         case WINED3DSPR_PREDICATE:  /* p0 */
         case WINED3DSPR_PRIMID:     /* primID */
         case WINED3DSPR_LOOP:       /* aL */
         case WINED3DSPR_PREDICATE:  /* p0 */
         case WINED3DSPR_PRIMID:     /* primID */
+        case WINED3DSPR_SAMPLEMASK: /* oMask */
             return TRUE;
 
         case WINED3DSPR_MISCTYPE:
             return TRUE;
 
         case WINED3DSPR_MISCTYPE:
@@ -4171,24 +4175,28 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
 }
 
 static inline void shader_get_position_fixup(const struct wined3d_context *context,
 }
 
 static inline void shader_get_position_fixup(const struct wined3d_context *context,
-        const struct wined3d_state *state, float *position_fixup)
+        const struct wined3d_state *state, unsigned int fixup_count, float *position_fixup)
 {
     float center_offset;
 {
     float center_offset;
+    unsigned int i;
 
     if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
         center_offset = 63.0f / 64.0f;
     else
         center_offset = -1.0f / 64.0f;
 
 
     if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
         center_offset = 63.0f / 64.0f;
     else
         center_offset = -1.0f / 64.0f;
 
-    position_fixup[0] = 1.0f;
-    position_fixup[1] = 1.0f;
-    position_fixup[2] = center_offset / state->viewport.width;
-    position_fixup[3] = -center_offset / state->viewport.height;
-
-    if (context->render_offscreen)
+    for (i = 0; i < fixup_count; ++i)
     {
     {
-        position_fixup[1] *= -1.0f;
-        position_fixup[3] *= -1.0f;
+        position_fixup[4 * i    ] = 1.0f;
+        position_fixup[4 * i + 1] = 1.0f;
+        position_fixup[4 * i + 2] = center_offset / state->viewports[i].width;
+        position_fixup[4 * i + 3] = -center_offset / state->viewports[i].height;
+
+        if (context->render_offscreen)
+        {
+            position_fixup[4 * i + 1] *= -1.0f;
+            position_fixup[4 * i + 3] *= -1.0f;
+        }
     }
 }
 
     }
 }
 
@@ -4292,8 +4300,8 @@ struct wined3d_rational
 struct wined3d_color_key_conversion
 {
     enum wined3d_format_id dst_format;
 struct wined3d_color_key_conversion
 {
     enum wined3d_format_id dst_format;
-    void (*convert)(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width,
-            unsigned int height, const struct wined3d_palette *palette, const struct wined3d_color_key *color_key);
+    void (*convert)(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch,
+            unsigned int width, unsigned int height, const struct wined3d_color_key *colour_key);
 };
 
 struct wined3d_format
 };
 
 struct wined3d_format
@@ -4511,15 +4519,6 @@ static inline void wined3d_insert_bits(DWORD *bitstream,
     }
 }
 
     }
 }
 
-static inline struct wined3d_surface *context_get_rt_surface(const struct wined3d_context *context)
-{
-    struct wined3d_texture *texture = context->current_rt.texture;
-
-    if (!texture)
-        return NULL;
-    return texture->sub_resources[context->current_rt.sub_resource_idx].u.surface;
-}
-
 static inline void wined3d_from_cs(const struct wined3d_cs *cs)
 {
     if (cs->thread)
 static inline void wined3d_from_cs(const struct wined3d_cs *cs)
 {
     if (cs->thread)
index 08e6479..1847393 100644 (file)
@@ -22,13 +22,13 @@ reactos/sdk/tools/wpp                   # Synced to WineStaging-2.9
 The following libraries are shared with Wine.
 
 reactos/dll/directx/wine/amstream       # Synced to WineStaging-3.9
 The following libraries are shared with Wine.
 
 reactos/dll/directx/wine/amstream       # Synced to WineStaging-3.9
-reactos/dll/directx/wine/d3d8           # Synced to WineStaging-3.3
-reactos/dll/directx/wine/d3d9           # Synced to WineStaging-3.3
+reactos/dll/directx/wine/d3d8           # Synced to WineStaging-3.9
+reactos/dll/directx/wine/d3d9           # Synced to WineStaging-3.9
 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3drm          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dxof         # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3drm          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dxof         # Synced to WineStaging-3.3
-reactos/dll/directx/wine/ddraw          # Synced to WineStaging-3.3
+reactos/dll/directx/wine/ddraw          # Synced to WineStaging-3.9
 reactos/dll/directx/wine/devenum        # Synced to WineStaging-3.3
 reactos/dll/directx/wine/dinput         # Synced to WineStaging-3.3
 reactos/dll/directx/wine/dinput8        # Synced to WineStaging-3.3
 reactos/dll/directx/wine/devenum        # Synced to WineStaging-3.3
 reactos/dll/directx/wine/dinput         # Synced to WineStaging-3.3
 reactos/dll/directx/wine/dinput8        # Synced to WineStaging-3.3
@@ -40,7 +40,7 @@ reactos/dll/directx/wine/dxdiagn        # Synced to WineStaging-3.3
 reactos/dll/directx/wine/msdmo          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/qedit          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/quartz         # Synced to WineStaging-3.3
 reactos/dll/directx/wine/msdmo          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/qedit          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/quartz         # Synced to WineStaging-3.3
-reactos/dll/directx/wine/wined3d        # Synced to WineStaging-3.3
+reactos/dll/directx/wine/wined3d        # Synced to WineStaging-3.9
 
 reactos/dll/win32/activeds            # Synced to WineStaging-3.3
 reactos/dll/win32/actxprxy            # Synced to WineStaging-3.3
 
 reactos/dll/win32/activeds            # Synced to WineStaging-3.3
 reactos/dll/win32/actxprxy            # Synced to WineStaging-3.3
index 1f8171d..dab9371 100644 (file)
@@ -388,12 +388,11 @@ enum wined3d_render_state
     WINED3D_RS_SRCBLENDALPHA                = 207,
     WINED3D_RS_DESTBLENDALPHA               = 208,
     WINED3D_RS_BLENDOPALPHA                 = 209,
     WINED3D_RS_SRCBLENDALPHA                = 207,
     WINED3D_RS_DESTBLENDALPHA               = 208,
     WINED3D_RS_BLENDOPALPHA                 = 209,
-    WINED3D_RS_DEPTHCLIP                    = 210,
-    WINED3D_RS_DEPTHBIASCLAMP               = 211,
-    WINED3D_RS_COLORWRITEENABLE4            = 212,
-    WINED3D_RS_COLORWRITEENABLE5            = 213,
-    WINED3D_RS_COLORWRITEENABLE6            = 214,
-    WINED3D_RS_COLORWRITEENABLE7            = 215,
+    WINED3D_RS_DEPTHBIASCLAMP               = 210,
+    WINED3D_RS_COLORWRITEENABLE4            = 211,
+    WINED3D_RS_COLORWRITEENABLE5            = 212,
+    WINED3D_RS_COLORWRITEENABLE6            = 213,
+    WINED3D_RS_COLORWRITEENABLE7            = 214,
 };
 #define WINEHIGHEST_RENDER_STATE                                WINED3D_RS_COLORWRITEENABLE7
 
 };
 #define WINEHIGHEST_RENDER_STATE                                WINED3D_RS_COLORWRITEENABLE7
 
@@ -531,6 +530,16 @@ enum wined3d_swap_effect
     WINED3D_SWAP_EFFECT_OVERLAY,
 };
 
     WINED3D_SWAP_EFFECT_OVERLAY,
 };
 
+enum wined3d_swap_interval
+{
+    WINED3D_SWAP_INTERVAL_IMMEDIATE = 0,
+    WINED3D_SWAP_INTERVAL_ONE       = 1,
+    WINED3D_SWAP_INTERVAL_TWO       = 2,
+    WINED3D_SWAP_INTERVAL_THREE     = 3,
+    WINED3D_SWAP_INTERVAL_FOUR      = 4,
+    WINED3D_SWAP_INTERVAL_DEFAULT   = ~0u,
+};
+
 enum wined3d_sampler_state
 {
     WINED3D_SAMP_ADDRESS_U                  = 1,
 enum wined3d_sampler_state
 {
     WINED3D_SAMP_ADDRESS_U                  = 1,
@@ -590,7 +599,7 @@ enum wined3d_texture_stage_state
     WINED3D_TSS_ALPHA_ARG0                  = 15,
     WINED3D_TSS_RESULT_ARG                  = 16,
     WINED3D_TSS_CONSTANT                    = 17,
     WINED3D_TSS_ALPHA_ARG0                  = 15,
     WINED3D_TSS_RESULT_ARG                  = 16,
     WINED3D_TSS_CONSTANT                    = 17,
-    WINED3D_TSS_INVALID                     = ~0U,
+    WINED3D_TSS_INVALID                     = ~0u,
 };
 #define WINED3D_HIGHEST_TEXTURE_STATE                           WINED3D_TSS_CONSTANT
 
 };
 #define WINED3D_HIGHEST_TEXTURE_STATE                           WINED3D_TSS_CONSTANT
 
@@ -940,13 +949,6 @@ enum wined3d_shader_byte_code_format
 
 #define WINED3DPRESENT_RATE_DEFAULT                             0x00000000
 
 
 #define WINED3DPRESENT_RATE_DEFAULT                             0x00000000
 
-#define WINED3DPRESENT_INTERVAL_DEFAULT                         0x00000000
-#define WINED3DPRESENT_INTERVAL_ONE                             0x00000001
-#define WINED3DPRESENT_INTERVAL_TWO                             0x00000002
-#define WINED3DPRESENT_INTERVAL_THREE                           0x00000004
-#define WINED3DPRESENT_INTERVAL_FOUR                            0x00000008
-#define WINED3DPRESENT_INTERVAL_IMMEDIATE                       0x80000000
-
 #define WINED3DCLIPPLANE0                                       (1u << 0)
 #define WINED3DCLIPPLANE1                                       (1u << 1)
 #define WINED3DCLIPPLANE2                                       (1u << 2)
 #define WINED3DCLIPPLANE0                                       (1u << 0)
 #define WINED3DCLIPPLANE1                                       (1u << 1)
 #define WINED3DCLIPPLANE2                                       (1u << 2)
@@ -1326,8 +1328,6 @@ enum wined3d_shader_byte_code_format
 #define WINED3D_NO_PRIMITIVE_RESTART                            0x00000800
 #define WINED3D_LEGACY_CUBEMAP_FILTERING                        0x00001000
 #define WINED3D_NORMALIZED_DEPTH_BIAS                           0x00002000
 #define WINED3D_NO_PRIMITIVE_RESTART                            0x00000800
 #define WINED3D_LEGACY_CUBEMAP_FILTERING                        0x00001000
 #define WINED3D_NORMALIZED_DEPTH_BIAS                           0x00002000
-#define WINED3D_REQUEST_D3D10                                   0x00004000
-#define WINED3D_LIMIT_VIEWPORT                                  0x00008000
 
 #define WINED3D_RESZ_CODE                                       0x7fa05000
 
 
 #define WINED3D_RESZ_CODE                                       0x7fa05000
 
@@ -1576,6 +1576,8 @@ enum wined3d_shader_byte_code_format
 #define WINED3D_VIEW_TEXTURE_CUBE                               0x00000008
 #define WINED3D_VIEW_TEXTURE_ARRAY                              0x00000010
 
 #define WINED3D_VIEW_TEXTURE_CUBE                               0x00000008
 #define WINED3D_VIEW_TEXTURE_ARRAY                              0x00000010
 
+#define WINED3D_MAX_VIEWPORTS                                   16
+
 struct wined3d_display_mode
 {
     UINT width;
 struct wined3d_display_mode
 {
     UINT width;
@@ -1729,10 +1731,10 @@ struct wined3d_adapter_identifier
 
 struct wined3d_swapchain_desc
 {
 
 struct wined3d_swapchain_desc
 {
-    UINT backbuffer_width;
-    UINT backbuffer_height;
+    unsigned int backbuffer_width;
+    unsigned int backbuffer_height;
     enum wined3d_format_id backbuffer_format;
     enum wined3d_format_id backbuffer_format;
-    UINT backbuffer_count;
+    unsigned int backbuffer_count;
     DWORD backbuffer_usage;
     enum wined3d_multisample_type multisample_type;
     DWORD multisample_quality;
     DWORD backbuffer_usage;
     enum wined3d_multisample_type multisample_type;
     DWORD multisample_quality;
@@ -1742,8 +1744,7 @@ struct wined3d_swapchain_desc
     BOOL enable_auto_depth_stencil;
     enum wined3d_format_id auto_depth_stencil_format;
     DWORD flags;
     BOOL enable_auto_depth_stencil;
     enum wined3d_format_id auto_depth_stencil_format;
     DWORD flags;
-    UINT refresh_rate;
-    UINT swap_interval;
+    unsigned int refresh_rate;
     BOOL auto_restore_display_mode;
 };
 
     BOOL auto_restore_display_mode;
 };
 
@@ -1889,7 +1890,6 @@ typedef struct _WINED3DCAPS
     DWORD Caps;
     DWORD Caps2;
     DWORD Caps3;
     DWORD Caps;
     DWORD Caps2;
     DWORD Caps3;
-    DWORD PresentationIntervals;
 
     DWORD CursorCaps;
     DWORD DevCaps;
 
     DWORD CursorCaps;
     DWORD DevCaps;
@@ -2008,6 +2008,7 @@ struct wined3d_blend_state_desc
 struct wined3d_rasterizer_state_desc
 {
     BOOL front_ccw;
 struct wined3d_rasterizer_state_desc
 {
     BOOL front_ccw;
+    BOOL depth_clip;
 };
 
 struct wined3d_sampler_desc
 };
 
 struct wined3d_sampler_desc
@@ -2138,11 +2139,8 @@ struct wined3d_device_parent_ops
     void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device);
     void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent);
     void (__cdecl *activate)(struct wined3d_device_parent *device_parent, BOOL activate);
     void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device);
     void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent);
     void (__cdecl *activate)(struct wined3d_device_parent *device_parent, BOOL activate);
-    HRESULT (__cdecl *surface_created)(struct wined3d_device_parent *device_parent,
-            struct wined3d_texture *texture, unsigned int sub_resource_idx,
-            void **parent, const struct wined3d_parent_ops **parent_ops);
-    HRESULT (__cdecl *volume_created)(struct wined3d_device_parent *device_parent,
-            struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
+    HRESULT (__cdecl *texture_sub_resource_created)(struct wined3d_device_parent *device_parent,
+            enum wined3d_resource_type type, struct wined3d_texture *texture, unsigned int sub_resource_idx,
             void **parent, const struct wined3d_parent_ops **parent_ops);
     HRESULT (__cdecl *create_swapchain_texture)(struct wined3d_device_parent *device_parent, void *parent,
             const struct wined3d_resource_desc *desc, DWORD texture_flags, struct wined3d_texture **texture);
             void **parent, const struct wined3d_parent_ops **parent_ops);
     HRESULT (__cdecl *create_swapchain_texture)(struct wined3d_device_parent *device_parent, void *parent,
             const struct wined3d_resource_desc *desc, DWORD texture_flags, struct wined3d_texture **texture);
@@ -2239,7 +2237,7 @@ void __cdecl wined3d_device_copy_resource(struct wined3d_device *device,
 HRESULT __cdecl wined3d_device_copy_sub_resource_region(struct wined3d_device *device,
         struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
         unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
 HRESULT __cdecl wined3d_device_copy_sub_resource_region(struct wined3d_device *device,
         struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
         unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
-        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box);
+        unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags);
 void __cdecl wined3d_device_copy_uav_counter(struct wined3d_device *device,
         struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav);
 HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx,
 void __cdecl wined3d_device_copy_uav_counter(struct wined3d_device *device,
         struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav);
 HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx,
@@ -2306,6 +2304,7 @@ HRESULT __cdecl wined3d_device_get_light(const struct wined3d_device *device,
         UINT light_idx, struct wined3d_light *light);
 HRESULT __cdecl wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable);
 void __cdecl wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material);
         UINT light_idx, struct wined3d_light *light);
 HRESULT __cdecl wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable);
 void __cdecl wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material);
+unsigned int __cdecl wined3d_device_get_max_frame_latency(const struct wined3d_device *device);
 float __cdecl wined3d_device_get_npatch_mode(const struct wined3d_device *device);
 struct wined3d_shader * __cdecl wined3d_device_get_pixel_shader(const struct wined3d_device *device);
 struct wined3d_query * __cdecl wined3d_device_get_predication(struct wined3d_device *device, BOOL *value);
 float __cdecl wined3d_device_get_npatch_mode(const struct wined3d_device *device);
 struct wined3d_shader * __cdecl wined3d_device_get_pixel_shader(const struct wined3d_device *device);
 struct wined3d_query * __cdecl wined3d_device_get_predication(struct wined3d_device *device, BOOL *value);
@@ -2329,7 +2328,8 @@ struct wined3d_rendertarget_view * __cdecl wined3d_device_get_rendertarget_view(
         unsigned int view_idx);
 DWORD __cdecl wined3d_device_get_sampler_state(const struct wined3d_device *device,
         UINT sampler_idx, enum wined3d_sampler_state state);
         unsigned int view_idx);
 DWORD __cdecl wined3d_device_get_sampler_state(const struct wined3d_device *device,
         UINT sampler_idx, enum wined3d_sampler_state state);
-void __cdecl wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect);
+void __cdecl wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count,
+        RECT *rect);
 BOOL __cdecl wined3d_device_get_software_vertex_processing(const struct wined3d_device *device);
 struct wined3d_buffer * __cdecl wined3d_device_get_stream_output(struct wined3d_device *device,
         UINT idx, UINT *offset);
 BOOL __cdecl wined3d_device_get_software_vertex_processing(const struct wined3d_device *device);
 struct wined3d_buffer * __cdecl wined3d_device_get_stream_output(struct wined3d_device *device,
         UINT idx, UINT *offset);
@@ -2349,7 +2349,8 @@ struct wined3d_unordered_access_view * __cdecl wined3d_device_get_unordered_acce
         const struct wined3d_device *device, unsigned int idx);
 struct wined3d_vertex_declaration * __cdecl wined3d_device_get_vertex_declaration(const struct wined3d_device *device);
 struct wined3d_shader * __cdecl wined3d_device_get_vertex_shader(const struct wined3d_device *device);
         const struct wined3d_device *device, unsigned int idx);
 struct wined3d_vertex_declaration * __cdecl wined3d_device_get_vertex_declaration(const struct wined3d_device *device);
 struct wined3d_shader * __cdecl wined3d_device_get_vertex_shader(const struct wined3d_device *device);
-void __cdecl wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport);
+void __cdecl wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count,
+        struct wined3d_viewport *viewports);
 struct wined3d_buffer * __cdecl wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx);
 HRESULT __cdecl wined3d_device_get_vs_consts_b(const struct wined3d_device *device,
         unsigned int start_idx, unsigned int count, BOOL *constants);
 struct wined3d_buffer * __cdecl wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx);
 HRESULT __cdecl wined3d_device_get_vs_consts_b(const struct wined3d_device *device,
         unsigned int start_idx, unsigned int count, BOOL *constants);
@@ -2425,6 +2426,7 @@ HRESULT __cdecl wined3d_device_set_light(struct wined3d_device *device,
         UINT light_idx, const struct wined3d_light *light);
 HRESULT __cdecl wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable);
 void __cdecl wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material);
         UINT light_idx, const struct wined3d_light *light);
 HRESULT __cdecl wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable);
 void __cdecl wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material);
+void __cdecl wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int max_frame_latency);
 void __cdecl wined3d_device_set_multithreaded(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments);
 void __cdecl wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader);
 void __cdecl wined3d_device_set_multithreaded(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments);
 void __cdecl wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader);
@@ -2450,7 +2452,8 @@ HRESULT __cdecl wined3d_device_set_rendertarget_view(struct wined3d_device *devi
         unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport);
 void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device,
         UINT sampler_idx, enum wined3d_sampler_state state, DWORD value);
         unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport);
 void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device,
         UINT sampler_idx, enum wined3d_sampler_state state, DWORD value);
-void __cdecl wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect);
+void __cdecl wined3d_device_set_scissor_rects(struct wined3d_device *device,
+        unsigned int rect_count, const RECT *rect);
 void __cdecl wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software);
 void __cdecl wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
         struct wined3d_buffer *buffer, UINT offset);
 void __cdecl wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software);
 void __cdecl wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
         struct wined3d_buffer *buffer, UINT offset);
@@ -2467,7 +2470,8 @@ void __cdecl wined3d_device_set_unordered_access_view(struct wined3d_device *dev
 void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device,
         struct wined3d_vertex_declaration *declaration);
 void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader);
 void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device,
         struct wined3d_vertex_declaration *declaration);
 void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader);
-void __cdecl wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport);
+void __cdecl wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count,
+        const struct wined3d_viewport *viewports);
 void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
 HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device,
         unsigned int start_idx, unsigned int count, const BOOL *constants);
 void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
 HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device,
         unsigned int start_idx, unsigned int count, const BOOL *constants);
@@ -2484,7 +2488,7 @@ HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device);
 void __cdecl wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
 HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device);
 void __cdecl wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
-        unsigned int depth_pitch);
+        unsigned int depth_pitch, unsigned int flags);
 HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device,
         struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture);
 HRESULT __cdecl wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes);
 HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device,
         struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture);
 HRESULT __cdecl wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes);
@@ -2685,8 +2689,8 @@ void __cdecl wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchai
 HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
         struct wined3d_raster_status *raster_status);
 ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain);
 HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
         struct wined3d_raster_status *raster_status);
 ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain);
-HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
-        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD swap_interval, DWORD flags);
+HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, DWORD flags);
 HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
         unsigned int width, unsigned int height, enum wined3d_format_id format_id,
         enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);
 HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
         unsigned int width, unsigned int height, enum wined3d_format_id format_id,
         enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);