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