From 81cffd7658765be610e53bcd9489a3d73597e5eb Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Thu, 3 Oct 2019 18:38:29 +0200 Subject: [PATCH] [D3D8][D3D9][DDRAW][D3DCOMPILER_43][WINED3D] Revert to Wine Staging 3.3 Avoid regressions CORE-14955 "Ddraw fullscreen crashes" and CORE-15652 This brings us back to before guilty commit 0.4.10-dev-55-g 7af3969e9fe68b5f55a088f93a6b69570822c733 and therefore downgrades dll/directx/wine/ D3D8,D3D9,DDRAW,D3DCOMPILER_43,WINED3D to WineStaging 3.3. Also downgrades related header sdk/include/reactos/wine/wined3d.h and for the first time also media/doc/README.WINE Same versions of these dlls we had in every ros rls since 0.4.10rls. Amine Khaldi agreed to perform this revert also for master now. Purpose of this revert is to fix crashes when Ddraw apps switch into fullscreen with VBEMP and inbuilt Mesa. I tested, before: DxDiag crashed when switching to fullscreen (CORE-14955), Diablo II crashed immediately (CORE-15652), Monster-Truck-Madness 2 demo crashed after main menu Afterwards all of these apps do run. DXTN does still work after that, even with VBEMP and inbuilt Mesa. squashed commit of 0.4.13-RC-2-g 67dd70e5ef0acc09495c8a0853cf2a1161f65101 and 0.4.13-RC-3-g 9f1e2cd172f3bf14da6b1c288fdc1dc3980cc63d --- dll/directx/wine/d3d8/CMakeLists.txt | 2 +- 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/CMakeLists.txt | 2 +- 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 +- .../wine/d3dcompiler_43/CMakeLists.txt | 15 +- dll/directx/wine/ddraw/CMakeLists.txt | 2 +- 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/CMakeLists.txt | 7 +- dll/directx/wine/wined3d/arb_program_shader.c | 359 ++- .../wine/wined3d/ati_fragment_shader.c | 37 +- dll/directx/wine/wined3d/buffer.c | 10 +- dll/directx/wine/wined3d/context.c | 1350 +++------- 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 +-------- .../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 | 2200 +++++++++-------- 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 | 10 +- sdk/include/reactos/wine/wined3d.h | 74 +- 47 files changed, 4685 insertions(+), 5257 deletions(-) diff --git a/dll/directx/wine/d3d8/CMakeLists.txt b/dll/directx/wine/d3d8/CMakeLists.txt index d3d49e2e76d..09d7a6c659d 100644 --- a/dll/directx/wine/d3d8/CMakeLists.txt +++ b/dll/directx/wine/d3d8/CMakeLists.txt @@ -19,7 +19,7 @@ list(APPEND SOURCE volume.c precomp.h) -add_library(d3d8 MODULE +add_library(d3d8 SHARED ${SOURCE} guid.c version.rc diff --git a/dll/directx/wine/d3d8/d3d8_private.h b/dll/directx/wine/d3d8/d3d8_private.h index 3fbc096b254..cba5dd647b4 100644 --- a/dll/directx/wine/d3d8/d3d8_private.h +++ b/dll/directx/wine/d3d8/d3d8_private.h @@ -166,11 +166,10 @@ 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, - unsigned int swap_interval, struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN; + 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 616886bcafa..5daf6f46c2a 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, DWORD presentation_interval) + const struct wined3d_swapchain_desc *swapchain_desc) { 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 = presentation_interval; + present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval; } static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) @@ -245,27 +245,6 @@ 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) { @@ -282,20 +261,6 @@ 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; @@ -313,6 +278,7 @@ 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) @@ -328,7 +294,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 = D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE; + caps->PresentationIntervals = wined3d_caps->PresentationIntervals; caps->CursorCaps = wined3d_caps->CursorCaps; caps->DevCaps = wined3d_caps->DevCaps; caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; @@ -377,57 +343,6 @@ 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); @@ -438,6 +353,8 @@ 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 */ @@ -781,8 +698,7 @@ 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; - unsigned int swap_interval; - unsigned int i, count; + UINT i, count; HRESULT hr; TRACE("iface %p, present_parameters %p, swapchain %p.\n", @@ -814,11 +730,9 @@ static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters)) return D3DERR_INVALIDCALL; - swap_interval = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); - if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, swap_interval, &object))) + if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, &object))) *swapchain = &object->IDirect3DSwapChain8_iface; - present_parameters_from_wined3d_swapchain_desc(present_parameters, - &desc, present_parameters->FullScreen_PresentationInterval); + present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); return hr; } @@ -892,8 +806,6 @@ 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); @@ -1619,30 +1531,10 @@ 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; @@ -1650,7 +1542,8 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3D vp.min_z = viewport->MinZ; vp.max_z = viewport->MaxZ; - wined3d_device_set_viewports(device->wined3d_device, 1, &vp); + wined3d_mutex_lock(); + wined3d_device_set_viewport(device->wined3d_device, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -1664,7 +1557,7 @@ static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPO TRACE("iface %p, viewport %p.\n", iface, viewport); wined3d_mutex_lock(); - wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); + wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); wined3d_mutex_unlock(); viewport->X = wined3d_viewport.x; @@ -2187,11 +2080,9 @@ 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) { - TRACE("iface %p, info_id %#x, info %p, info_size %u.\n", iface, info_id, info, info_size); + FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size); - if (info_id < 4) - return E_FAIL; - return S_FALSE; + return D3D_OK; } static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface, @@ -3271,40 +3162,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_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, +static HRESULT CDECL device_parent_surface_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, 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); + struct d3d8_surface *d3d_surface; - if (type == WINED3D_RTYPE_TEXTURE_2D) - { - struct d3d8_surface *d3d_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); - if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) - return E_OUTOFMEMORY; + 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); - } - else if (type == WINED3D_RTYPE_TEXTURE_3D) - { - struct d3d8_volume *d3d_volume; + surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_surface; + TRACE("Created surface %p.\n", d3d_surface); - if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) - return E_OUTOFMEMORY; + return D3D_OK; +} - 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; - } +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; + + 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; + + volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_volume; + TRACE("Created volume %p.\n", d3d_volume); return D3D_OK; } @@ -3343,7 +3234,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, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain))) + if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain))) { WARN("Failed to create swapchain, hr %#x.\n", hr); *swapchain = NULL; @@ -3362,7 +3253,8 @@ 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_texture_sub_resource_created, + device_parent_surface_created, + device_parent_volume_created, device_parent_create_swapchain_texture, device_parent_create_swapchain, }; @@ -3464,8 +3356,7 @@ 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, parameters->FullScreen_PresentationInterval); + present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc); device->declArraySize = 16; if (!(device->decls = heap_alloc(device->declArraySize * sizeof(*device->decls)))) @@ -3477,8 +3368,6 @@ 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 68300c0a655..6e8f93a25c6 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_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT; 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 39e3b238739..3a588b5e8c2 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, swapchain->swap_interval, 0); + src_rect, dst_rect, dst_window_override, 0, 0); wined3d_mutex_unlock(); return hr; @@ -167,13 +167,12 @@ 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, unsigned int swap_interval) + struct wined3d_swapchain_desc *desc) { 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, @@ -193,7 +192,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, - unsigned int swap_interval, struct d3d8_swapchain **swapchain) + struct d3d8_swapchain **swapchain) { struct d3d8_swapchain *object; HRESULT hr; @@ -201,7 +200,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, swap_interval))) + if (FAILED(hr = swapchain_init(object, device, desc))) { WARN("Failed to initialize swapchain, hr %#x.\n", hr); heap_free(object); diff --git a/dll/directx/wine/d3d9/CMakeLists.txt b/dll/directx/wine/d3d9/CMakeLists.txt index 14dd3e65320..223606b87ee 100644 --- a/dll/directx/wine/d3d9/CMakeLists.txt +++ b/dll/directx/wine/d3d9/CMakeLists.txt @@ -21,7 +21,7 @@ list(APPEND SOURCE volume.c precomp.h) -add_library(d3d9 MODULE +add_library(d3d9 SHARED ${SOURCE} guid.c version.rc diff --git a/dll/directx/wine/d3d9/d3d9_private.h b/dll/directx/wine/d3d9/d3d9_private.h index 408661306ad..094707a0d16 100644 --- a/dll/directx/wine/d3d9/d3d9_private.h +++ b/dll/directx/wine/d3d9/d3d9_private.h @@ -55,7 +55,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, DWORD presentation_interval) DECLSPEC_HIDDEN; + const struct wined3d_swapchain_desc *swapchain_desc) DECLSPEC_HIDDEN; void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps) DECLSPEC_HIDDEN; struct d3d9 @@ -99,6 +99,7 @@ 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; @@ -148,11 +149,10 @@ 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, - unsigned int swap_interval, struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN; + 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 2f3ad2880d6..bc73699e525 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, DWORD presentation_interval) + const struct wined3d_swapchain_desc *swapchain_desc) { 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 = presentation_interval; + present_parameters->PresentationInterval = swapchain_desc->swap_interval; } static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) @@ -270,27 +270,6 @@ 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) { @@ -309,19 +288,6 @@ 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; @@ -339,6 +305,7 @@ 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) @@ -363,7 +330,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 = D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE; + caps->PresentationIntervals = wined3d_caps->PresentationIntervals; caps->CursorCaps = wined3d_caps->CursorCaps; caps->DevCaps = wined3d_caps->DevCaps; caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; @@ -776,8 +743,7 @@ 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; - unsigned int swap_interval; - unsigned int i, count; + UINT i, count; HRESULT hr; TRACE("iface %p, present_parameters %p, swapchain %p.\n", @@ -810,11 +776,9 @@ 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; - swap_interval = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval); - if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, swap_interval, &object))) + if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object))) *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface; - present_parameters_from_wined3d_swapchain_desc(present_parameters, - &desc, present_parameters->PresentationInterval); + present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); return hr; } @@ -970,8 +934,6 @@ 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; @@ -981,6 +943,10 @@ 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) @@ -1010,8 +976,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - struct d3d9_swapchain *swapchain; - unsigned int i; + UINT i; HRESULT hr; TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n", @@ -1026,9 +991,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * wined3d_mutex_lock(); for (i = 0; i < device->implicit_swapchain_count; ++i) { - 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))) + if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, + src_rect, dst_rect, dst_window_override, 0, 0))) { wined3d_mutex_unlock(); return hr; @@ -1536,7 +1500,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, 0); + src->sub_resource_idx, &src_box); if (SUCCEEDED(hr) && dst->texture) d3d9_texture_flag_auto_gen_mipmap(dst->texture); @@ -2068,7 +2032,7 @@ static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D vp.max_z = viewport->MaxZ; wined3d_mutex_lock(); - wined3d_device_set_viewports(device->wined3d_device, 1, &vp); + wined3d_device_set_viewport(device->wined3d_device, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -2082,7 +2046,7 @@ static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEW TRACE("iface %p, viewport %p.\n", iface, viewport); wined3d_mutex_lock(); - wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); + wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); wined3d_mutex_unlock(); viewport->X = wined3d_viewport.x; @@ -2398,6 +2362,13 @@ 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; @@ -2564,7 +2535,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_rects(device->wined3d_device, 1, rect); + wined3d_device_set_scissor_rect(device->wined3d_device, rect); wined3d_mutex_unlock(); return D3D_OK; @@ -2577,7 +2548,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_rects(device->wined3d_device, NULL, rect); + wined3d_device_get_scissor_rect(device->wined3d_device, rect); wined3d_mutex_unlock(); return D3D_OK; @@ -2641,15 +2612,11 @@ 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) { - struct wined3d_texture *texture; - unsigned int i, stage; + unsigned int 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)); - } + for (i = 0; i < ARRAY_SIZE(device->textures); ++i) + if (device->textures[i]) + d3d9_texture_gen_auto_mipmap(device->textures[i]); } static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, @@ -3700,8 +3667,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex const RGNDATA *dirty_region, DWORD flags) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - struct d3d9_swapchain *swapchain; - unsigned int i; + UINT i; HRESULT hr; TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n", @@ -3717,9 +3683,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex wined3d_mutex_lock(); for (i = 0; i < device->implicit_swapchain_count; ++i) { - 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))) + if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, + src_rect, dst_rect, dst_window_override, 0, flags))) { wined3d_mutex_unlock(); return hr; @@ -3762,31 +3727,21 @@ 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 > 30) - return D3DERR_INVALIDCALL; - - wined3d_mutex_lock(); - wined3d_device_set_max_frame_latency(device->wined3d_device, max_latency); - wined3d_mutex_unlock(); + if (max_latency) + FIXME("Ignoring max_latency %u.\n", max_latency); return S_OK; } static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency) { - struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - - TRACE("iface %p, max_latency %p.\n", iface, max_latency); + FIXME("iface %p, max_latency %p stub!\n", iface, max_latency); - wined3d_mutex_lock(); - *max_latency = wined3d_device_get_max_frame_latency(device->wined3d_device); - wined3d_mutex_unlock(); + *max_latency = 2; - return S_OK; + return E_NOTIMPL; } static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window) @@ -4095,40 +4050,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_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, +static HRESULT CDECL device_parent_surface_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, 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); + struct d3d9_surface *d3d_surface; - if (type == WINED3D_RTYPE_TEXTURE_2D) - { - struct d3d9_surface *d3d_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); - if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) - return E_OUTOFMEMORY; + 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); - } - else if (type == WINED3D_RTYPE_TEXTURE_3D) - { - 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); - if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) - return E_OUTOFMEMORY; + return D3D_OK; +} - 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; - } +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; + + 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; + + volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_volume; + TRACE("Created volume %p.\n", d3d_volume); return D3D_OK; } @@ -4173,7 +4128,8 @@ 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 = d3d9_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain))) + hr = d3d9_swapchain_create(device, desc, &d3d_swapchain); + if (FAILED(hr)) { WARN("Failed to create swapchain, hr %#x.\n", hr); *swapchain = NULL; @@ -4192,7 +4148,8 @@ 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_texture_sub_resource_created, + device_parent_surface_created, + device_parent_volume_created, device_parent_create_swapchain_texture, device_parent_create_swapchain, }; @@ -4315,16 +4272,10 @@ 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], parameters[i].PresentationInterval); + present_parameters_from_wined3d_swapchain_desc(¶meters[i], &swapchain_desc[i]); } wined3d_mutex_unlock(); diff --git a/dll/directx/wine/d3d9/directx.c b/dll/directx/wine/d3d9/directx.c index 98f4a99c494..644766c2e97 100644 --- a/dll/directx/wine/d3d9/directx.c +++ b/dll/directx/wine/d3d9/directx.c @@ -254,12 +254,6 @@ 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) { @@ -585,7 +579,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_NORMALIZED_DEPTH_BIAS | WINED3D_LIMIT_VIEWPORT; if (!extended) flags |= WINED3D_VIDMEM_ACCOUNTING; diff --git a/dll/directx/wine/d3d9/swapchain.c b/dll/directx/wine/d3d9/swapchain.c index d303f3f9564..dbb3f45b91d 100644 --- a/dll/directx/wine/d3d9/swapchain.c +++ b/dll/directx/wine/d3d9/swapchain.c @@ -25,27 +25,6 @@ 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); @@ -158,7 +137,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, swapchain->swap_interval, flags); + src_rect, dst_rect, dst_window_override, 0, flags); wined3d_mutex_unlock(); return hr; @@ -272,15 +251,13 @@ 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, presentation_interval); + present_parameters_from_wined3d_swapchain_desc(parameters, &desc); return D3D_OK; } @@ -367,13 +344,12 @@ 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, unsigned int swap_interval) + struct wined3d_swapchain_desc *desc) { 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, @@ -393,7 +369,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, - unsigned int swap_interval, struct d3d9_swapchain **swapchain) + struct d3d9_swapchain **swapchain) { struct d3d9_swapchain *object; HRESULT hr; @@ -401,7 +377,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, swap_interval))) + if (FAILED(hr = swapchain_init(object, device, desc))) { 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 7b74ac5b9e8..c97fa6b0219 100644 --- a/dll/directx/wine/d3d9/texture.c +++ b/dll/directx/wine/d3d9/texture.c @@ -1339,22 +1339,9 @@ 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; } - 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; - } + flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; texture->autogen_filter_type = D3DTEXF_LINEAR; + levels = 0; } else { diff --git a/dll/directx/wine/d3dcompiler_43/CMakeLists.txt b/dll/directx/wine/d3dcompiler_43/CMakeLists.txt index 88d2383b7b6..7c5cb428400 100644 --- a/dll/directx/wine/d3dcompiler_43/CMakeLists.txt +++ b/dll/directx/wine/d3dcompiler_43/CMakeLists.txt @@ -3,19 +3,18 @@ add_definitions( -D__WINESRC__ -DDIRECT3D_VERSION=0x0900) -if(MSVC) - # error C4133: 'function': incompatible types - from 'D3D_CBUFFER_TYPE *' to 'DWORD *' - replace_compile_flags("/we4133" " ") -endif() - include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) spec2def(d3dcompiler_43.dll d3dcompiler_43.spec ADD_IMPORTLIB) list(APPEND SOURCE asmparser.c + asmshader.tab.c + asmshader.yy.c blob.c bytecodewriter.c compiler.c + hlsl.tab.c + hlsl.yy.c main.c reflection.c utils.c @@ -24,10 +23,6 @@ list(APPEND SOURCE add_library(d3dcompiler_43 MODULE ${SOURCE} - asmshader.tab.c - asmshader.yy.c - hlsl.tab.c - hlsl.yy.c version.rc ${CMAKE_CURRENT_BINARY_DIR}/d3dcompiler_43.def) @@ -43,5 +38,5 @@ set_module_type(d3dcompiler_43 win32dll) target_link_libraries(d3dcompiler_43 dx10guid uuid wine wpp) add_importlibs(d3dcompiler_43 msvcrt kernel32 ntdll) add_dependencies(d3dcompiler_43 d3d_idl_headers) -add_pch(d3dcompiler_43 precomp.h SOURCE) +#add_pch(d3dcompiler_43 precomp.h SOURCE) add_cd_file(TARGET d3dcompiler_43 DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/wine/ddraw/CMakeLists.txt b/dll/directx/wine/ddraw/CMakeLists.txt index 03029bdc8f9..6141d630f3f 100644 --- a/dll/directx/wine/ddraw/CMakeLists.txt +++ b/dll/directx/wine/ddraw/CMakeLists.txt @@ -29,7 +29,7 @@ if(MSVC) set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/FIwine/typeof.h") endif() -add_library(ddraw MODULE +add_library(ddraw SHARED ${SOURCE} ddraw.rc ${CMAKE_CURRENT_BINARY_DIR}/ddraw.def) diff --git a/dll/directx/wine/ddraw/ddraw.c b/dll/directx/wine/ddraw/ddraw.c index 6b5ccece46d..e5205c0d000 100644 --- a/dll/directx/wine/ddraw/ddraw.c +++ b/dll/directx/wine/ddraw/ddraw.c @@ -633,9 +633,8 @@ 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 = 0; - swapchain_desc.backbuffer_count = 1; - swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD; + swapchain_desc.backbuffer_usage = WINED3DUSAGE_RENDERTARGET; + swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; swapchain_desc.device_window = window; swapchain_desc.windowed = windowed; swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; @@ -2100,7 +2099,7 @@ static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface) ddraw->flags |= DDRAW_GDI_FLIP; if (ddraw->primary) - ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE, 0); + ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE); return DD_OK; } @@ -4910,19 +4909,18 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw) ddraw->device_state = DDRAW_DEVICE_STATE_OK; } -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, +static HRESULT CDECL device_parent_surface_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 ddraw *ddraw = ddraw_from_device_parent(device_parent); struct ddraw_surface *ddraw_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); /* We have a swapchain or wined3d internal texture. */ - if (type != WINED3D_RTYPE_TEXTURE_2D || !wined3d_texture_get_parent(wined3d_texture) - || wined3d_texture_get_parent(wined3d_texture) == ddraw) + if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw) { *parent = NULL; *parent_ops = &ddraw_null_wined3d_parent_ops; @@ -4947,6 +4945,19 @@ static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_d 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; @@ -4963,26 +4974,25 @@ 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) - parent_ops = &ddraw_frontbuffer_parent_ops; - else - parent_ops = &ddraw_null_wined3d_parent_ops; + if (ddraw->wined3d_frontbuffer) + { + ERR("Frontbuffer already created.\n"); + return E_FAIL; + } if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1, - texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, parent_ops, texture))) + texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture))) { WARN("Failed to create texture, hr %#x.\n", hr); return hr; } - if (!ddraw->wined3d_frontbuffer) - ddraw->wined3d_frontbuffer = *texture; + ddraw->wined3d_frontbuffer = *texture; return hr; } @@ -5013,7 +5023,8 @@ 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_texture_sub_resource_created, + device_parent_surface_created, + device_parent_volume_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 1bba80cf261..cac38c57e92 100644 --- a/dll/directx/wine/ddraw/ddraw_private.h +++ b/dll/directx/wine/ddraw/ddraw_private.h @@ -57,15 +57,14 @@ struct FvfToDecl #define DDRAW_NO3D 0x00000008 #define DDRAW_SCL_DDRAW1 0x00000010 #define DDRAW_SCL_RECURSIVE 0x00000020 -#define DDRAW_SWAPPED 0x00000040 -#define DDRAW_GDI_FLIP 0x00000080 +#define DDRAW_GDI_FLIP 0x00000040 #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_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT) enum ddraw_device_state { @@ -219,7 +218,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, unsigned int swap_interval) DECLSPEC_HIDDEN; + const RECT *rect, BOOL read) 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 799b2bcaa00..24dbd3be505 100644 --- a/dll/directx/wine/ddraw/device.c +++ b/dll/directx/wine/ddraw/device.c @@ -5296,12 +5296,25 @@ 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); @@ -5309,23 +5322,6 @@ 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; @@ -5333,7 +5329,8 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi vp.min_z = viewport->dvMinZ; vp.max_z = viewport->dvMaxZ; - wined3d_device_set_viewports(device->wined3d_device, 1, &vp); + wined3d_mutex_lock(); + wined3d_device_set_viewport(device->wined3d_device, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -5356,6 +5353,21 @@ 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); @@ -5367,7 +5379,7 @@ static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi return DDERR_INVALIDPARAMS; wined3d_mutex_lock(); - wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); + wined3d_device_get_viewport(device->wined3d_device, &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 e2c4fc11ab4..17bea2764c5 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, 0); + wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box); break; default: @@ -610,16 +610,9 @@ 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; @@ -666,7 +659,7 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * buffer->src_vertex_pos = 0; } - if (data->dwVertexCount && (!buf_size || data->dwVertexOffset < buf_size)) + if (data->dwVertexCount) { box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX); box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX); @@ -674,11 +667,8 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * 0, &map_desc, &box, WINED3D_MAP_WRITE))) return hr; - 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); + memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, + data->dwVertexCount * sizeof(D3DVERTEX)); wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0); } @@ -706,11 +696,12 @@ 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); - /* Tests show that dwSize is ignored. */ - memcpy(data, &buffer->data, sizeof(*data)); + dwSize = data->dwSize; + memcpy(data, &buffer->data, dwSize); if (TRACE_ON(ddraw)) { diff --git a/dll/directx/wine/ddraw/palette.c b/dll/directx/wine/ddraw/palette.c index 87aec96443a..5148832cab6 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, 0); + ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE); wined3d_mutex_unlock(); diff --git a/dll/directx/wine/ddraw/surface.c b/dll/directx/wine/ddraw/surface.c index df8d0380093..11a0e6ba8db 100644 --- a/dll/directx/wine/ddraw/surface.c +++ b/dll/directx/wine/ddraw/surface.c @@ -40,22 +40,15 @@ 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, unsigned int swap_interval) +HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read) { - struct wined3d_texture *dst_texture; + struct ddraw *ddraw = surface->ddraw; 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); @@ -70,25 +63,15 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, if (w <= 0 || h <= 0) return DD_OK; - if (surface->ddraw->swapchain_window && !(surface->ddraw->flags & DDRAW_GDI_FLIP)) + if (ddraw->swapchain_window && !(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; - 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; + return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect, + surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT); } if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc))) @@ -491,7 +474,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, 0); + ddraw_surface_update_frontbuffer(surface, NULL, FALSE); } if (palette_impl) IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface); @@ -1007,7 +990,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, 0); + hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE); if (SUCCEEDED(hr)) hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, &map_desc, rect ? &box : NULL, @@ -1196,7 +1179,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, 0); + hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE); wined3d_mutex_unlock(); return hr; @@ -1241,24 +1224,6 @@ 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) { @@ -1372,7 +1337,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 & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) + if (flags) { static UINT once; if (!once++) @@ -1382,7 +1347,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, ddraw_swap_interval_from_flags(flags)); + hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE); else hr = DD_OK; @@ -1523,11 +1488,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, 0); + hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE); 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, 0); + hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE); return hr; } @@ -1570,7 +1535,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, 0))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE))) break; } } @@ -1581,7 +1546,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, 0))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE))) break; } } @@ -2254,7 +2219,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, 0); + hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE); if (SUCCEEDED(hr)) hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc); @@ -2358,7 +2323,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, 0); + hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE); } wined3d_mutex_unlock(); @@ -4326,12 +4291,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, 0); + hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE); 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, 0); + hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE); wined3d_mutex_unlock(); switch(hr) diff --git a/dll/directx/wine/ddraw/utils.c b/dll/directx/wine/ddraw/utils.c index b0a028d4a57..65f24dc13fd 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 | DDLOCK_WRITEONLY))) + if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS))) 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_WRITEONLY | DDLOCK_NODIRTYUPDATE); + flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | 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 f2caf20858e..6ef3226c4d1 100644 --- a/dll/directx/wine/ddraw/viewport.c +++ b/dll/directx/wine/ddraw/viewport.c @@ -249,118 +249,109 @@ static HRESULT WINAPI d3d_viewport_Initialize(IDirect3DViewport3 *iface, IDirect return DDERR_ALREADYINITIALIZED; } -static HRESULT WINAPI d3d_viewport_GetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *vp) +/***************************************************************************** + * 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) { - struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); - DWORD size; - - TRACE("iface %p, vp %p.\n", iface, vp); + struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); + DWORD dwSize; - if (!vp) - return DDERR_INVALIDPARAMS; + TRACE("iface %p, data %p.\n", iface, lpData); wined3d_mutex_lock(); - size = vp->dwSize; - if (!viewport->use_vp2) - { - memcpy(vp, &viewport->viewports.vp1, size); - } - else - { + dwSize = lpData->dwSize; + if (!This->use_vp2) + memcpy(lpData, &(This->viewports.vp1), dwSize); + else { D3DVIEWPORT vp1; - vp1.dwSize = sizeof(vp1); - 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.dwX = This->viewports.vp2.dwX; + vp1.dwY = This->viewports.vp2.dwY; + vp1.dwWidth = This->viewports.vp2.dwWidth; + vp1.dwHeight = This->viewports.vp2.dwHeight; vp1.dvMaxX = 0.0; vp1.dvMaxY = 0.0; vp1.dvScaleX = 0.0; vp1.dvScaleY = 0.0; - vp1.dvMinZ = viewport->viewports.vp2.dvMinZ; - vp1.dvMaxZ = viewport->viewports.vp2.dvMaxZ; - memcpy(vp, &vp1, size); + vp1.dvMinZ = This->viewports.vp2.dvMinZ; + vp1.dvMaxZ = This->viewports.vp2.dvMaxZ; + memcpy(lpData, &vp1, dwSize); } if (TRACE_ON(ddraw)) { TRACE(" returning D3DVIEWPORT :\n"); - _dump_D3DVIEWPORT(vp); + _dump_D3DVIEWPORT(lpData); } wined3d_mutex_unlock(); - return D3D_OK; + return DD_OK; } -static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *vp) +/***************************************************************************** + * 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) { - 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; + struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); IDirect3DViewport3 *current_viewport; - struct ddraw_surface *surface; - TRACE("iface %p, vp %p.\n", iface, vp); - - if (!vp) - return DDERR_INVALIDPARAMS; + TRACE("iface %p, data %p.\n", iface, lpData); if (TRACE_ON(ddraw)) { TRACE(" getting D3DVIEWPORT :\n"); - _dump_D3DVIEWPORT(vp); - } - - if (!device) - { - WARN("Viewport not bound to a device, returning D3DERR_VIEWPORTHASNODEVICE.\n"); - return D3DERR_VIEWPORTHASNODEVICE; + _dump_D3DVIEWPORT(lpData); } wined3d_mutex_lock(); - if (device->version > 1) - { - 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) - { - 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); + This->use_vp2 = 0; + memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1)); + memcpy(&(This->viewports.vp1), lpData, lpData->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; + /* 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; - if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(&device->IDirect3DDevice3_iface, ¤t_viewport))) + if (This->active_device) { - if (current_viewport == iface) - viewport_activate(viewport, FALSE); - IDirect3DViewport3_Release(current_viewport); + IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; + if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport))) + { + if (current_viewport == iface) viewport_activate(This, FALSE); + IDirect3DViewport3_Release(current_viewport); + } } wined3d_mutex_unlock(); - return D3D_OK; + return DD_OK; } /***************************************************************************** @@ -891,44 +882,53 @@ static HRESULT WINAPI d3d_viewport_NextLight(IDirect3DViewport3 *iface, * IDirect3DViewport2 Methods. *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *vp) +/***************************************************************************** + * 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) { - struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); - DWORD size; - - TRACE("iface %p, vp %p.\n", iface, vp); + struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); + DWORD dwSize; - if (!vp) - return DDERR_INVALIDPARAMS; + TRACE("iface %p, data %p.\n", iface, lpData); wined3d_mutex_lock(); - size = vp->dwSize; - if (viewport->use_vp2) - { - memcpy(vp, &viewport->viewports.vp2, size); - } - else - { + dwSize = lpData->dwSize; + if (This->use_vp2) + memcpy(lpData, &(This->viewports.vp2), dwSize); + else { D3DVIEWPORT2 vp2; - vp2.dwSize = sizeof(vp2); - 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.dwX = This->viewports.vp1.dwX; + vp2.dwY = This->viewports.vp1.dwY; + vp2.dwWidth = This->viewports.vp1.dwWidth; + vp2.dwHeight = This->viewports.vp1.dwHeight; vp2.dvClipX = 0.0; vp2.dvClipY = 0.0; vp2.dvClipWidth = 0.0; vp2.dvClipHeight = 0.0; - vp2.dvMinZ = viewport->viewports.vp1.dvMinZ; - vp2.dvMaxZ = viewport->viewports.vp1.dvMaxZ; - memcpy(vp, &vp2, size); + vp2.dvMinZ = This->viewports.vp1.dvMinZ; + vp2.dvMaxZ = This->viewports.vp1.dvMaxZ; + memcpy(lpData, &vp2, dwSize); } if (TRACE_ON(ddraw)) { TRACE(" returning D3DVIEWPORT2 :\n"); - _dump_D3DVIEWPORT2(vp); + _dump_D3DVIEWPORT2(lpData); } wined3d_mutex_unlock(); @@ -936,64 +936,47 @@ static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVI return D3D_OK; } -static HRESULT WINAPI d3d_viewport_SetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *vp) +/***************************************************************************** + * 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) { - 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; + struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); IDirect3DViewport3 *current_viewport; - struct ddraw_surface *surface; - - TRACE("iface %p, vp %p.\n", iface, vp); - if (!vp) - return DDERR_INVALIDPARAMS; + TRACE("iface %p, data %p.\n", iface, lpData); if (TRACE_ON(ddraw)) { TRACE(" getting D3DVIEWPORT2 :\n"); - _dump_D3DVIEWPORT2(vp); - } - - if (!device) - { - WARN("Viewport not bound to a device, returning D3DERR_VIEWPORTHASNODEVICE.\n"); - return D3DERR_VIEWPORTHASNODEVICE; + _dump_D3DVIEWPORT2(lpData); } wined3d_mutex_lock(); - if (device->version > 1) - { - 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); + This->use_vp2 = 1; + memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2)); + memcpy(&(This->viewports.vp2), lpData, lpData->dwSize); - 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 (This->active_device) + { + IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; + if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport))) { - WARN("Invalid viewport, returning DDERR_INVALIDPARAMS.\n"); - wined3d_mutex_unlock(); - return DDERR_INVALIDPARAMS; + if (current_viewport == iface) viewport_activate(This, FALSE); + IDirect3DViewport3_Release(current_viewport); } } - 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/CMakeLists.txt b/dll/directx/wine/wined3d/CMakeLists.txt index 6a6bf74e108..235adab9027 100644 --- a/dll/directx/wine/wined3d/CMakeLists.txt +++ b/dll/directx/wine/wined3d/CMakeLists.txt @@ -7,11 +7,6 @@ add_definitions( include_directories(BEFORE ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -if(MSVC) - # error C4312: 'type cast': conversion from 'LONG' to 'void *' of greater size - replace_compile_flags("/we4312" " ") -endif() - # We name this d3dwine.dll, because the Virtualbox additions ship with a custom wined3d.dll # and it breaks everything if it is installed. spec2def(d3dwine.dll wined3d.spec ADD_IMPORTLIB) @@ -46,7 +41,7 @@ list(APPEND SOURCE wined3d_main.c precomp.h) -add_library(d3dwine MODULE +add_library(d3dwine SHARED ${SOURCE} version.rc ${CMAKE_CURRENT_BINARY_DIR}/d3dwine.def) diff --git a/dll/directx/wine/wined3d/arb_program_shader.c b/dll/directx/wine/wined3d/arb_program_shader.c index 4fbb3a59ecd..f86c167b606 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, 1, position_fixup); + shader_get_position_fixup(context, state, 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 != WINED3D_VP_MODE_SHADER) + else if(ctx->cur_ps_args->super.vp_mode != vertexshader) { /* 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,6 +1416,9 @@ 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; @@ -1429,8 +1432,12 @@ 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) - && ins->ctx->gl_info->supported[ARB_TEXTURE_RECTANGLE]) + && gl_info->supported[ARB_TEXTURE_RECTANGLE]) tex_type = "RECT"; else tex_type = "2D"; @@ -3415,68 +3422,73 @@ static void init_ps_input(const struct wined3d_shader *shader, const char *semantic_name; DWORD 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; - } + 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; - /* 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; + 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"; + } - 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"; - } + TRACE("v%u, semantic %s%u is %s\n", input->register_idx, + semantic_name, semantic_idx, priv->ps_input[input->register_idx]); + } + break; - TRACE("v%u, semantic %s%u is %s\n", input->register_idx, - semantic_name, semantic_idx, priv->ps_input[input->register_idx]); + 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; } } @@ -6072,19 +6084,17 @@ 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, BOOL tmp_dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) + BOOL alpha, DWORD 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"; - dstreg = tmp_dst ? "tempreg" : "ret"; + if(dst == tempreg) dstreg = "tempreg"; + else dstreg = "ret"; arg0 = get_argreg(buffer, 0, stage, dw_arg0); arg1 = get_argreg(buffer, 1, stage, dw_arg1); @@ -6263,7 +6273,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].tmp_dst) + if (settings->op[stage].dst == tempreg) tempreg_used = TRUE; if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) tempreg_used = TRUE; @@ -6381,17 +6391,12 @@ 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 == WINED3D_PROJECTION_NONE) - { + if(settings->op[stage].projected == proj_none) { instr = "TEX"; - } - else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4 - || settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) - { + } else if(settings->op[stage].projected == proj_count4 || + settings->op[stage].projected == proj_count3) { instr = "TXP"; - } - else - { + } else { FIXME("Unexpected projection mode %d\n", settings->op[stage].projected); instr = "TXP"; } @@ -6405,27 +6410,18 @@ 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 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) - { + /* 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) { 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); } @@ -6437,16 +6433,12 @@ 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 == WINED3D_PROJECTION_COUNT3) - { + } else if(settings->op[stage].projected == proj_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); } @@ -6495,23 +6487,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].tmp_dst, + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].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].tmp_dst, + gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].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].tmp_dst, + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].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].tmp_dst, + gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst, settings->op[stage].aop, settings->op[stage].aarg0, settings->op[stage].aarg1, settings->op[stage].aarg2); } @@ -6936,8 +6928,8 @@ static void arbfp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3 heap_free(arbfp_blitter); } -static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, - const struct arbfp_blit_type *type, char *luminance) +static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, + char *luminance) { char chroma; const char *tex, *texinstr = "TXP"; @@ -6985,12 +6977,13 @@ static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n"); shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n"); - /* 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. */ + /* 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 + */ 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 */ @@ -7019,10 +7012,12 @@ static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, /* This gives the correctly filtered luminance value */ shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex); + + return TRUE; } -static void gen_yv12_read(struct wined3d_string_buffer *buffer, - const struct arbfp_blit_type *type, char *luminance) +static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, + char *luminance) { const char *tex; static const float yv12_coef[] @@ -7084,6 +7079,7 @@ static void gen_yv12_read(struct wined3d_string_buffer *buffer, */ 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"); @@ -7091,7 +7087,7 @@ static void gen_yv12_read(struct wined3d_string_buffer *buffer, 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"); @@ -7105,11 +7101,11 @@ static void gen_yv12_read(struct wined3d_string_buffer *buffer, } else { - /* The y coordinate for V is in the range [size, size + size / 4). */ + /* Read from [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"); @@ -7165,10 +7161,12 @@ static void gen_yv12_read(struct wined3d_string_buffer *buffer, shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); } *luminance = 'a'; + + return TRUE; } -static void gen_nv12_read(struct wined3d_string_buffer *buffer, - const struct arbfp_blit_type *type, char *luminance) +static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, + char *luminance) { const char *tex; static const float nv12_coef[] @@ -7244,7 +7242,7 @@ static void gen_nv12_read(struct wined3d_string_buffer *buffer, } else { - /* The y coordinate for chroma is in the range [size, size + size / 2). */ + /* Read from [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"); @@ -7299,6 +7297,8 @@ static void gen_nv12_read(struct wined3d_string_buffer *buffer, shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); } *luminance = 'a'; + + return TRUE; } /* Context activation is done by the caller. */ @@ -7464,15 +7464,27 @@ static GLuint gen_yuv_shader(const struct wined3d_gl_info *gl_info, const struct { case COMPLEX_FIXUP_UYVY: case COMPLEX_FIXUP_YUY2: - gen_packed_yuv_read(&buffer, type, &luminance_component); + if (!gen_planar_yuv_read(&buffer, type, &luminance_component)) + { + string_buffer_free(&buffer); + return 0; + } break; case COMPLEX_FIXUP_YV12: - gen_yv12_read(&buffer, type, &luminance_component); + if (!gen_yv12_read(&buffer, type, &luminance_component)) + { + string_buffer_free(&buffer); + return 0; + } break; case COMPLEX_FIXUP_NV12: - gen_nv12_read(&buffer, type, &luminance_component); + if (!gen_nv12_read(&buffer, type, &luminance_component)) + { + string_buffer_free(&buffer); + return 0; + } break; default: @@ -7698,7 +7710,7 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op, const struct wine enum complex_fixup src_fixup; BOOL decompress; - if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) + if (!context->gl_info->supported[ARB_FRAGMENT_PROGRAM]) return FALSE; if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id) @@ -7783,105 +7795,59 @@ 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_texture *src_texture, unsigned int src_sub_resource_idx, - DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, - unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, + struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, + const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { + 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)) - { - 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); + 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); } arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter); - if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) - { - struct wined3d_resource_desc desc; - struct wined3d_box upload_box; - HRESULT hr; - - TRACE("Source texture is not GPU accessible, creating a staging texture.\n"); - - src_level = src_sub_resource_idx % src_texture->level_count; - desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; - desc.format = src_texture->resource.format->id; - desc.multisample_type = src_texture->resource.multisample_type; - desc.multisample_quality = src_texture->resource.multisample_quality; - desc.usage = WINED3DUSAGE_PRIVATE; - desc.access = WINED3D_RESOURCE_ACCESS_GPU; - desc.width = wined3d_texture_get_level_width(src_texture, src_level); - desc.height = wined3d_texture_get_level_height(src_texture, src_level); - desc.depth = 1; - desc.size = 0; - - if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0, - NULL, NULL, &wined3d_null_parent_ops, &staging_texture))) - { - ERR("Failed to create staging texture, hr %#x.\n", hr); - return dst_location; - } - - wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth); - wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0, - src_texture, src_sub_resource_idx, &upload_box); - - src_texture = staging_texture; - src_sub_resource_idx = 0; - } - else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO - && (src_texture->sub_resources[src_sub_resource_idx].locations - & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE + /* 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 && !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. */ - texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context); + surface_load_fb_texture(src_surface, 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_ffp_blit_state(context, device); + context_apply_blit_state(context, device); if (dst_location == WINED3D_LOCATION_DRAWABLE) { d = *dst_rect; - wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d); + surface_translate_drawable_coords(dst_surface, context->win_handle, &d); dst_rect = &d; } @@ -7891,16 +7857,15 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl if (dst_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Destination texture %p is onscreen.\n", dst_texture); + TRACE("Destination surface %p is onscreen.\n", dst_surface); buffer = wined3d_texture_get_gl_buffer(dst_texture); } else { - TRACE("Destination texture %p is offscreen.\n", dst_texture); + TRACE("Destination surface %p is offscreen.\n", dst_surface); buffer = GL_COLOR_ATTACHMENT0; } - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, - &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location); context_set_draw_buffer(context, buffer); context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -7917,16 +7882,14 @@ 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 */ - context_draw_textured_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter); + draw_textured_quad(src_texture, src_sub_resource_idx, context, src_rect, dst_rect, filter); /* Leave the opengl state valid for blitting */ arbfp_blit_unset(context->gl_info); - 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); + 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. */ return dst_location; } diff --git a/dll/directx/wine/wined3d/ati_fragment_shader.c b/dll/directx/wine/wined3d/ati_fragment_shader.c index 9a1cae34cd7..9d6837a2f22 100644 --- a/dll/directx/wine/wined3d/ati_fragment_shader.c +++ b/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -341,8 +341,9 @@ static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES]) lowest_read = i; } - if (lowest_write == -1 && op[i].tmp_dst) + if(lowest_write == -1 && op[i].dst == tempreg) { 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) { @@ -504,13 +505,16 @@ 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 == WINED3D_PROJECTION_NONE) + GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, + GL_TEXTURE0_ARB + stage, + GL_SWIZZLE_STR_ATI)); + if(op[stage + 1].projected == proj_none) { swizzle = GL_SWIZZLE_STR_ATI; - else if (op[stage + 1].projected == WINED3D_PROJECTION_COUNT4) + } else if(op[stage + 1].projected == proj_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, @@ -575,12 +579,13 @@ 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 == WINED3D_PROJECTION_NONE) + if(op[stage].projected == proj_none) { swizzle = GL_SWIZZLE_STR_ATI; - else if (op[stage].projected == WINED3D_PROJECTION_COUNT3) + } else if(op[stage].projected == proj_count3) { swizzle = GL_SWIZZLE_STR_DR_ATI; - else + } else { swizzle = GL_SWIZZLE_STQ_DQ_ATI; + } if (op_reads_texture(&op[stage])) { @@ -619,18 +624,14 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], break; } - 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; + 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; 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 9baf0556dda..cae7ef87885 100644 --- a/dll/directx/wine/wined3d/buffer.c +++ b/dll/directx/wine/wined3d/buffer.c @@ -615,7 +615,10 @@ 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: @@ -1180,6 +1183,8 @@ 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); @@ -1375,9 +1380,6 @@ 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); @@ -1426,7 +1428,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); + 0, NULL, data->data, data->row_pitch, data->slice_pitch); return WINED3D_OK; } diff --git a/dll/directx/wine/wined3d/context.c b/dll/directx/wine/wined3d/context.c index 0ee5b65bc1c..8a8d952c3ff 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,6 +164,7 @@ 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 { @@ -252,8 +253,6 @@ 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}, @@ -457,15 +456,19 @@ static inline void context_set_fbo_key_for_render_target(const struct wined3d_co } texture = wined3d_texture_from_resource(resource); - if (texture->current_renderbuffer) + if (resource->type == WINED3D_RTYPE_TEXTURE_2D) { - 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; - } + 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].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; @@ -612,7 +615,10 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, } else if (depth_stencil->resource->type == WINED3D_RTYPE_TEXTURE_2D) { - wined3d_texture_set_compatible_renderbuffer(ds_texture, ds_level, &render_targets[0]); + struct wined3d_surface *surface; + + surface = ds_texture->sub_resources[depth_stencil->sub_resource_idx].u.surface; + surface_set_compatible_renderbuffer(surface, &render_targets[0]); } } @@ -755,8 +761,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, - const struct wined3d_rendertarget_info *render_targets, - const struct wined3d_rendertarget_info *depth_stencil, DWORD color_location, DWORD ds_location) + struct wined3d_rendertarget_info *render_targets, struct wined3d_surface *depth_stencil, + DWORD color_location, DWORD ds_location) { struct fbo_entry *entry, *entry2; @@ -778,35 +784,32 @@ 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, depth_stencil, color_location, ds_location); + render_targets, &ds, 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_resource *rt, unsigned int rt_sub_resource_idx, - struct wined3d_resource *ds, unsigned int ds_sub_resource_idx, DWORD location) + struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) { - struct wined3d_rendertarget_info ds_info = {{0}}; - memset(context->blit_targets, 0, sizeof(context->blit_targets)); - if (rt) + if (render_target) { - context->blit_targets[0].resource = rt; - context->blit_targets[0].sub_resource_idx = rt_sub_resource_idx; + 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].layer_count = 1; } - - 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_apply_fbo_state(context, target, context->blit_targets, depth_stencil, location, location); } /* Context activation is done by the caller. */ @@ -1067,22 +1070,34 @@ 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) +void context_resource_released(const struct wined3d_device *device, + struct wined3d_resource *resource, enum wined3d_resource_type type) { - unsigned int i; + struct wined3d_texture *texture; + UINT i; if (!device->d3d_initialized) return; - for (i = 0; i < device->context_count; ++i) + switch (type) { - struct wined3d_context *context = device->contexts[i]; + case WINED3D_RTYPE_TEXTURE_2D: + case WINED3D_RTYPE_TEXTURE_3D: + texture = texture_from_resource(resource); - if (&context->current_rt.texture->resource == resource) - { - context->current_rt.texture = NULL; - context->current_rt.sub_resource_idx = 0; - } + 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; + + default: + break; } } @@ -1092,7 +1107,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_texture_update(struct wined3d_context *context, const struct wined3d_texture *texture) +void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) { const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry = context->current_fbo; @@ -1102,10 +1117,10 @@ void context_texture_update(struct wined3d_context *context, const struct wined3 for (i = 0; i < gl_info->limits.buffers + 1; ++i) { - if (texture->texture_rgb.name == entry->key.objects[i].object - || texture->texture_srgb.name == entry->key.objects[i].object) + if (surface->container->texture_rgb.name == entry->key.objects[i].object + || surface->container->texture_srgb.name == entry->key.objects[i].object) { - TRACE("Updated texture %p is bound as attachment %u to the current FBO.\n", texture, i); + TRACE("Updated surface %p is bound as attachment %u to the current FBO.\n", surface, i); context->rebind_fbo = TRUE; return; } @@ -1451,9 +1466,6 @@ static void context_destroy_gl_resources(struct wined3d_context *context) } } - if (context->blit_vbo) - GL_EXTCALL(glDeleteBuffers(1, &context->blit_vbo)); - checkGLcall("context cleanup"); } @@ -1591,12 +1603,14 @@ 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_texture *texture, unsigned int sub_resource_idx) +void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) { - if (context->current_rt.texture != texture || context->current_rt.sub_resource_idx != sub_resource_idx) + if (context->current_rt.texture != restore->container + || context->current_rt.sub_resource_idx != surface_get_sub_resource_idx(restore)) { context_release(context); - context = context_acquire(texture->resource.device, texture, sub_resource_idx); + context = context_acquire(restore->container->resource.device, + restore->container, surface_get_sub_resource_idx(restore)); } context_release(context); @@ -1777,7 +1791,6 @@ 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); @@ -1853,6 +1866,8 @@ 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; @@ -1862,20 +1877,9 @@ 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 (gl_info->selected_gl_version >= MAKEDWORD_VERSION(3, 2)) + if (ctx_flags & 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; - } + ctx_attribs[ctx_attrib_idx - 1] &= ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 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()); @@ -2172,6 +2176,15 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, 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 @@ -2257,10 +2270,6 @@ 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; @@ -2359,6 +2368,28 @@ 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; @@ -2407,6 +2438,206 @@ 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); @@ -2525,9 +2756,11 @@ 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); @@ -2667,7 +2900,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_RASTERIZER); + context_invalidate_state(context, STATE_FRONTFACE); context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN); context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); } @@ -2734,12 +2967,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_resource *rt) +static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context, struct wined3d_texture *rt) { - if (!rt || rt->format->id == WINED3DFMT_NULL) + if (!rt || rt->resource.format->id == WINED3DFMT_NULL) return 0; - else if (rt->type != WINED3D_RTYPE_BUFFER && texture_from_resource(rt)->swapchain) - return context_generate_rt_mask_from_resource(rt); + else if (rt->swapchain) + return context_generate_rt_mask_from_resource(&rt->resource); else return context_generate_rt_mask(context_get_offscreen_gl_buffer(context)); } @@ -2747,13 +2980,9 @@ 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) { @@ -2761,8 +2990,8 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine { wined3d_texture_load(rt, context, FALSE); - context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, &rt->resource, - context->current_rt.sub_resource_idx, NULL, 0, rt->resource.draw_binding); + 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); if (rt->resource.format->id != WINED3DFMT_NULL) rt_mask = 1; else @@ -2777,7 +3006,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine } else { - rt_mask = context_generate_rt_mask_no_fbo(context, &rt->resource); + rt_mask = context_generate_rt_mask_no_fbo(context, rt); } cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; @@ -2792,235 +3021,49 @@ 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); +} - context_get_rt_size(context, &rt_size); +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 (context->last_was_blit) + if (ds) + return TRUE; + + for (i = 0; i < rt_count; ++i) { - 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; + if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL) + return TRUE; } - context->last_was_blit = TRUE; - if (gl_info->supported[ARB_SAMPLER_OBJECTS]) - GL_EXTCALL(glBindSampler(0, 0)); - context_active_texture(context, gl_info, 0); + return FALSE; +} - sampler = context->rev_tex_unit_map[0]; - if (sampler != WINED3D_UNMAPPED_STAGE) +/* 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 (sampler < MAX_TEXTURES) + if (!have_framebuffer_attachment(rt_count, rts, dsv)) { - 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 (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; + 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)) @@ -3038,22 +3081,14 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win 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, + 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, &ds_info, + 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); } @@ -3065,7 +3100,8 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win } else { - rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ? rts[0]->resource : NULL); + rt_mask = context_generate_rt_mask_no_fbo(context, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0])->container : NULL); } } else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO @@ -3079,7 +3115,8 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win } else { - rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ? rts[0]->resource : NULL); + rt_mask = context_generate_rt_mask_no_fbo(context, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0])->container : NULL); } cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; @@ -3097,7 +3134,6 @@ 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 @@ -3129,7 +3165,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, rts[0]->resource); + return context_generate_rt_mask_no_fbo(context, wined3d_rendertarget_view_get_surface(rts[0])->container); else if (!context->render_offscreen) return context_generate_rt_mask_from_resource(rts[0]->resource); @@ -3166,11 +3202,9 @@ 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, &ds_info, + context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE); } else @@ -3191,16 +3225,8 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat if (!color_location) color_location = fb->render_targets[i]->resource->draw_binding; } - - if (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, + context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, + wined3d_rendertarget_view_get_surface(fb->depth_stencil), color_location, fb->depth_stencil ? fb->depth_stencil->resource->draw_binding : 0); } } @@ -4027,7 +4053,6 @@ 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; } @@ -4089,7 +4114,6 @@ 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) @@ -4353,6 +4377,9 @@ 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); } @@ -4538,7 +4565,6 @@ 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; @@ -5026,12 +5052,13 @@ 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; @@ -5059,9 +5086,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s } else if (!context->transform_feedback_active) { - 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); + GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type); GL_EXTCALL(glBeginTransformFeedback(mode)); checkGLcall("glBeginTransformFeedback"); context->transform_feedback_active = 1; @@ -5116,663 +5141,8 @@ 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); - 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); + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ - 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); + context_release(context); } diff --git a/dll/directx/wine/wined3d/cs.c b/dll/directx/wine/wined3d/cs.c index eb24d94e9a7..460fe12c7dc 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_VIEWPORTS, - WINED3D_CS_OP_SET_SCISSOR_RECTS, + WINED3D_CS_OP_SET_VIEWPORT, + WINED3D_CS_OP_SET_SCISSOR_RECT, 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; - unsigned int swap_interval; + DWORD swap_interval; DWORD flags; }; @@ -138,18 +138,16 @@ struct wined3d_cs_set_predication BOOL value; }; -struct wined3d_cs_set_viewports +struct wined3d_cs_set_viewport { enum wined3d_cs_op opcode; - unsigned int viewport_count; - struct wined3d_viewport viewports[1]; + struct wined3d_viewport viewport; }; -struct wined3d_cs_set_scissor_rects +struct wined3d_cs_set_scissor_rect { enum wined3d_cs_op opcode; - unsigned int rect_count; - RECT rects[1]; + RECT rect; }; struct wined3d_cs_set_rendertarget_view @@ -408,7 +406,9 @@ 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,7 +456,12 @@ 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); - wined3d_swapchain_set_swap_interval(swapchain, op->swap_interval); + + if (op->swap_interval && swapchain->desc.swap_interval != op->swap_interval) + { + swapchain->desc.swap_interval = op->swap_interval; + swapchain_update_swap_interval(swapchain); + } swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags); @@ -471,7 +476,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, - unsigned int swap_interval, DWORD flags) + DWORD swap_interval, DWORD flags) { struct wined3d_cs_present *op; unsigned int i; @@ -497,8 +502,9 @@ 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. */ - while (pending >= swapchain->max_frame_latency) + * ahead of the worker thread. We have a constant limit here, but + * IDXGIDevice1 allows tuning this. */ + while (pending > 1) { wined3d_pause(); pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); @@ -532,24 +538,19 @@ 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->viewports[0]; - struct wined3d_rendertarget_view *view; + const struct wined3d_viewport *vp = &state->viewport; 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; - if (flags & WINED3DCLEAR_TARGET) - op->rt_count = rt_count; - else - op->rt_count = 0; + op->rt_count = rt_count; 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_rects[0]); + IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rect); op->color = *color; op->depth = depth; op->stencil = stencil; @@ -560,21 +561,12 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * { for (i = 0; i < rt_count; ++i) { - 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 (state->fb->render_targets[i]) + wined3d_resource_acquire(state->fb->render_targets[i]->resource); } } if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) - { - 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); - } + wined3d_resource_acquire(state->fb->depth_stencil->resource); cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -782,7 +774,6 @@ 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; @@ -802,8 +793,6 @@ 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; @@ -969,53 +958,40 @@ 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_viewports(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_viewports *op = data; + const struct wined3d_cs_set_viewport *op = data; - 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; + cs->state.viewport = op->viewport; device_invalidate_state(cs->device, STATE_VIEWPORT); } -void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, - const struct wined3d_viewport *viewports) +void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) { - struct wined3d_cs_set_viewports *op; + struct wined3d_cs_set_viewport *op; - 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; + op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_VIEWPORT; + op->viewport = *viewport; cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } -static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_scissor_rects *op = data; + const struct wined3d_cs_set_scissor_rect *op = data; - 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; + cs->state.scissor_rect = op->rect; device_invalidate_state(cs->device, STATE_SCISSORRECT); } -void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects) +void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) { - struct wined3d_cs_set_scissor_rects *op; + struct wined3d_cs_set_scissor_rect *op; - 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; + op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; + op->rect = *rect; cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -1047,14 +1023,16 @@ 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) && prev->resource->type != WINED3D_RTYPE_BUFFER) + if ((prev = cs->state.fb->depth_stencil)) { - struct wined3d_texture *prev_texture = texture_from_resource(prev->resource); + struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev); - if (device->swapchains[0]->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL - || prev_texture->flags & WINED3D_TEXTURE_DISCARD) - wined3d_texture_validate_location(prev_texture, + 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, prev->sub_resource_idx, WINED3D_LOCATION_DISCARDED); + } } cs->fb.depth_stencil = op->view; @@ -1492,7 +1470,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_RASTERIZER); + device_invalidate_state(cs->device, STATE_FRONTFACE); } void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, @@ -2081,6 +2059,23 @@ 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; @@ -2115,6 +2110,13 @@ 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); @@ -2149,9 +2151,8 @@ 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, - 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_upload_data(dst_texture, op->dst_sub_resource_idx, context, &op->dst_box, + wined3d_const_bo_address(&addr), row_pitch, slice_pitch); 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); @@ -2159,10 +2160,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * } else { - 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"); + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(op->dst_resource->type)); } error: @@ -2211,7 +2209,6 @@ 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); @@ -2248,9 +2245,8 @@ 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_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_upload_data(texture, op->sub_resource_idx, context, + box, &addr, op->data.row_pitch, op->data.slice_pitch); 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); @@ -2266,6 +2262,7 @@ 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) @@ -2311,6 +2308,7 @@ 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; @@ -2324,6 +2322,10 @@ 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); } @@ -2464,8 +2466,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_VIEWPORTS */ wined3d_cs_exec_set_viewports, - /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects, + /* 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_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, @@ -2506,11 +2508,13 @@ 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)) @@ -2564,7 +2568,9 @@ 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, @@ -2601,6 +2607,7 @@ 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); @@ -2614,6 +2621,7 @@ 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); @@ -2675,6 +2683,7 @@ 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()) @@ -2683,6 +2692,7 @@ 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()) @@ -2705,7 +2715,9 @@ 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 8b4b3f9bb2c..e2b27e0cf43 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) } } -enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) +static 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,19 +238,10 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c BOOL render_offscreen; unsigned int i; - if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER) - { - target = texture_from_resource(rtv->resource); - context = context_acquire(device, target, rtv->sub_resource_idx); - } + if (target) + context = context_acquire(device, target->container, 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); @@ -290,11 +281,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->level_count; + unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->container->level_count; render_offscreen = TRUE; - drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level); - drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level); + 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); } if (depth_stencil) @@ -411,7 +402,9 @@ 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 { @@ -446,14 +439,16 @@ 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 (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target) - gl_info->gl_ops.gl.p_glFlush(); + 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. */ context_release(context); } @@ -682,11 +677,12 @@ 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); @@ -756,8 +752,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_2d_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); } if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) @@ -1040,8 +1036,7 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object) return; } wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info); - if (!wined3d_glsl_blitter_create(&device->blitter, device)) - wined3d_arbfp_blitter_create(&device->blitter, device); + wined3d_arbfp_blitter_create(&device->blitter, device); wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info); wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info); @@ -1089,7 +1084,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, goto err_out; } - if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_usage & WINED3DUSAGE_RENDERTARGET) + if (swapchain_desc->backbuffer_count) { struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; struct wined3d_view_desc view_desc; @@ -1125,7 +1120,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, TRACE("All defaults now set up.\n"); /* Clear the screen */ - if (device->back_buffer_view) + if (swapchain->back_buffers && swapchain->back_buffers[0]) clear_flags |= WINED3DCLEAR_TARGET; if (swapchain_desc->enable_auto_depth_stencil) clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL; @@ -1217,7 +1212,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) wine_rb_clear(&device->samplers, device_free_sampler, NULL); +#if defined(STAGING_CSMT) context_set_current(NULL); +#endif /* STAGING_CSMT */ wined3d_device_delete_opengl_contexts(device); if (device->fb.depth_stencil) @@ -1931,24 +1928,13 @@ INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *devi return device->state.base_vertex_index; } -void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count, - const struct wined3d_viewport *viewports) +void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport) { - unsigned int i; + TRACE("device %p, viewport %p.\n", device, viewport); + TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", + viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z); - TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports); - - for (i = 0; i < viewport_count; ++i) - { - TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i, viewports[i].x, viewports[i].y, - viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z); - } - - if (viewport_count) - memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports)); - else - memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports)); - device->update_state->viewport_count = viewport_count; + device->update_state->viewport = *viewport; /* Handle recording of state blocks */ if (device->recording) @@ -1958,21 +1944,14 @@ void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned return; } - wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports); + wined3d_cs_emit_set_viewport(device->cs, viewport); } -void CDECL wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count, - struct wined3d_viewport *viewports) +void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport) { - unsigned int count; - - TRACE("device %p, viewport_count %p, viewports %p.\n", device, viewport_count, viewports); + TRACE("device %p, viewport %p.\n", device, viewport); - count = viewport_count ? min(*viewport_count, device->state.viewport_count) : 1; - if (count && viewports) - memcpy(viewports, device->state.viewports, count * sizeof(*viewports)); - if (viewport_count) - *viewport_count = device->state.viewport_count; + *viewport = device->state.viewport; } static void resolve_depth_buffer(struct wined3d_device *device) @@ -2144,33 +2123,19 @@ DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device return device->state.sampler_states[sampler_idx][state]; } -void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsigned int rect_count, - const RECT *rects) +void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect) { - unsigned int i; - - TRACE("device %p, rect_count %u, rects %p.\n", device, rect_count, rects); - - for (i = 0; i < rect_count; ++i) - { - TRACE("%u: %s\n", i, wine_dbgstr_rect(&rects[i])); - } + TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect)); if (device->recording) device->recording->changed.scissorRect = TRUE; - if (device->update_state->scissor_rect_count == rect_count - && !memcmp(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects))) + if (EqualRect(&device->update_state->scissor_rect, rect)) { - TRACE("App is setting the old scissor rectangles over, nothing to do.\n"); + TRACE("App is setting the old scissor rectangle over, nothing to do.\n"); return; } - - if (rect_count) - memcpy(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects)); - else - memset(device->update_state->scissor_rects, 0, sizeof(device->update_state->scissor_rects)); - device->update_state->scissor_rect_count = rect_count; + CopyRect(&device->update_state->scissor_rect, rect); if (device->recording) { @@ -2178,20 +2143,15 @@ void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsig return; } - wined3d_cs_emit_set_scissor_rects(device->cs, rect_count, rects); + wined3d_cs_emit_set_scissor_rect(device->cs, rect); } -void CDECL wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count, RECT *rects) +void CDECL wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect) { - unsigned int count; - - TRACE("device %p, rect_count %p, rects %p.\n", device, rect_count, rects); + TRACE("device %p, rect %p.\n", device, rect); - count = rect_count ? min(*rect_count, device->state.scissor_rect_count) : 1; - if (count && rects) - memcpy(rects, device->state.scissor_rects, count * sizeof(*rects)); - if (rect_count) - *rect_count = device->state.scissor_rect_count; + *rect = device->state.scissor_rect; + TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect)); } void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device, @@ -3105,23 +3065,6 @@ struct wined3d_unordered_access_view * CDECL wined3d_device_get_unordered_access return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx); } -void CDECL wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int latency) -{ - unsigned int i; - - if (!latency) - latency = 3; - - device->max_frame_latency = latency; - for (i = 0; i < device->swapchain_count; ++i) - swapchain_set_max_frame_latency(device->swapchains[i], device); -} - -unsigned int CDECL wined3d_device_get_max_frame_latency(const struct wined3d_device *device) -{ - return device->max_frame_latency; -} - /* Context activation is done by the caller. */ #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, @@ -3203,8 +3146,8 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44); /* Get the viewport */ - wined3d_device_get_viewports(device, NULL, &vp); - TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n", + wined3d_device_get_viewport(device, &vp); + TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n", vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z); multiply_matrix(&mat,&view_mat,&world_mat); @@ -3919,9 +3862,12 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, level_count = min(src_level_count, dst_level_count); src_size = max(src_texture->resource.width, src_texture->resource.height); - src_size = max(src_size, src_texture->resource.depth); dst_size = max(dst_texture->resource.width, dst_texture->resource.height); - dst_size = max(dst_size, dst_texture->resource.depth); + if (type == WINED3D_RTYPE_TEXTURE_3D) + { + src_size = max(src_size, src_texture->resource.depth); + dst_size = max(dst_size, dst_texture->resource.depth); + } while (src_size > dst_size) { src_size >>= 1; @@ -4175,17 +4121,14 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource, - unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags) + unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) { struct wined3d_box dst_box, b; TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " - "src_resource %p, src_sub_resource_idx %u, src_box %s, flags %#x.\n", + "src_resource %p, src_sub_resource_idx %u, src_box %s.\n", device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z, - src_resource, src_sub_resource_idx, debug_box(src_box), flags); - - if (flags) - FIXME("Ignoring flags %#x.\n", flags); + src_resource, src_sub_resource_idx, debug_box(src_box)); if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx) { @@ -4250,7 +4193,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev wined3d_box_set(&dst_box, dst_x, 0, dst_x + (src_box->right - src_box->left), 1, 0, 1); } - else + else if (dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) { struct wined3d_texture *dst_texture = texture_from_resource(dst_resource); struct wined3d_texture *src_texture = texture_from_resource(src_resource); @@ -4268,6 +4211,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev return WINED3DERR_INVALIDCALL; } +#if !defined(STAGING_CSMT) if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) { WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); @@ -4278,22 +4222,33 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev { WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); return WINED3DERR_INVALIDCALL; +#else /* STAGING_CSMT */ + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || + src_texture->sub_resources[src_sub_resource_idx].map_count) + { + struct wined3d_device *device = dst_texture->resource.device; + device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || + src_texture->sub_resources[src_sub_resource_idx].map_count) + { + WARN("Destination or source sub-resource is mapped.\n"); + return WINEDDERR_SURFACEBUSY; + } +#endif /* STAGING_CSMT */ } if (!src_box) { - unsigned int src_w, src_h, src_d, dst_w, dst_h, dst_d, dst_level; + unsigned int src_w, src_h, dst_w, dst_h, dst_level; src_w = wined3d_texture_get_level_width(src_texture, src_level); src_h = wined3d_texture_get_level_height(src_texture, src_level); - src_d = wined3d_texture_get_level_depth(src_texture, src_level); dst_level = dst_sub_resource_idx % dst_texture->level_count; dst_w = wined3d_texture_get_level_width(dst_texture, dst_level) - dst_x; dst_h = wined3d_texture_get_level_height(dst_texture, dst_level) - dst_y; - dst_d = wined3d_texture_get_level_depth(dst_texture, dst_level) - dst_z; - wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, min(src_d, dst_d)); + wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, 1); src_box = &b; } else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box))) @@ -4303,7 +4258,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev } wined3d_box_set(&dst_box, dst_x, dst_y, dst_x + (src_box->right - src_box->left), - dst_y + (src_box->bottom - src_box->top), dst_z, dst_z + (src_box->back - src_box->front)); + dst_y + (src_box->bottom - src_box->top), 0, 1); if (FAILED(wined3d_texture_check_box_dimensions(dst_texture, dst_sub_resource_idx % dst_texture->level_count, &dst_box))) { @@ -4311,6 +4266,11 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev return WINED3DERR_INVALIDCALL; } } + else + { + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type)); + return WINED3DERR_INVALIDCALL; + } wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); @@ -4320,17 +4280,13 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, - unsigned int depth_pitch, unsigned int flags) + unsigned int depth_pitch) { unsigned int width, height, depth; struct wined3d_box b; - TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u, " - "flags %#x.\n", - device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch, flags); - - if (flags) - FIXME("Ignoring flags %#x.\n", flags); + TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n", + device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch); if (resource->type == WINED3D_RTYPE_BUFFER) { @@ -4344,7 +4300,8 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str height = 1; depth = 1; } - else + else if (resource->type == WINED3D_RTYPE_TEXTURE_1D || + resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D) { struct wined3d_texture *texture = texture_from_resource(resource); unsigned int level; @@ -4360,6 +4317,11 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str height = wined3d_texture_get_level_height(texture, level); depth = wined3d_texture_get_level_depth(texture, level); } + else + { + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); + return; + } if (!box) { @@ -4374,6 +4336,10 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str return; } +#if !defined(STAGING_CSMT) + wined3d_resource_wait_idle(resource); + +#endif /* STAGING_CSMT */ wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); } @@ -4437,7 +4403,7 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi return WINED3D_OK; resource = view->resource; - if (resource->type != WINED3D_RTYPE_TEXTURE_1D && resource->type != WINED3D_RTYPE_TEXTURE_2D) + if (resource->type != WINED3D_RTYPE_TEXTURE_2D) { FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); return WINED3DERR_INVALIDCALL; @@ -4526,20 +4492,19 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device { struct wined3d_state *state = &device->state; - state->viewports[0].x = 0; - state->viewports[0].y = 0; - state->viewports[0].width = view->width; - state->viewports[0].height = view->height; - state->viewports[0].min_z = 0.0f; - state->viewports[0].max_z = 1.0f; - state->viewport_count = 1; - wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports); + state->viewport.x = 0; + state->viewport.y = 0; + state->viewport.width = view->width; + state->viewport.height = view->height; + state->viewport.min_z = 0.0f; + state->viewport.max_z = 1.0f; + wined3d_cs_emit_set_viewport(device->cs, &state->viewport); - SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height); - state->scissor_rect_count = 1; - wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects); + SetRect(&state->scissor_rect, 0, 0, view->width, view->height); + wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect); } + prev = device->fb.render_targets[view_idx]; if (view == prev) return WINED3D_OK; @@ -4871,9 +4836,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc->auto_depth_stencil_format)); TRACE("flags %#x\n", swapchain_desc->flags); TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate); + TRACE("swap_interval %u\n", swapchain_desc->swap_interval); TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode); - if (swapchain_desc->backbuffer_usage && swapchain_desc->backbuffer_usage != WINED3DUSAGE_RENDERTARGET) + if (swapchain_desc->backbuffer_usage != WINED3DUSAGE_RENDERTARGET) FIXME("Got unexpected backbuffer usage %#x.\n", swapchain_desc->backbuffer_usage); if (swapchain_desc->swap_effect != WINED3D_SWAP_EFFECT_DISCARD @@ -4887,6 +4853,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, swapchain->desc.auto_depth_stencil_format = swapchain_desc->auto_depth_stencil_format; swapchain->desc.flags = swapchain_desc->flags; swapchain->desc.refresh_rate = swapchain_desc->refresh_rate; + swapchain->desc.swap_interval = swapchain_desc->swap_interval; swapchain->desc.auto_restore_display_mode = swapchain_desc->auto_restore_display_mode; if (swapchain_desc->device_window @@ -4988,7 +4955,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, wined3d_rendertarget_view_decref(device->back_buffer_view); device->back_buffer_view = NULL; } - if (swapchain->desc.backbuffer_count && swapchain->desc.backbuffer_usage & WINED3DUSAGE_RENDERTARGET) + if (swapchain->desc.backbuffer_count) { struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource; @@ -5039,22 +5006,21 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, wined3d_device_set_rendertarget_view(device, 0, view, FALSE); /* Note the min_z / max_z is not reset. */ - state->viewports[0].x = 0; - state->viewports[0].y = 0; - state->viewports[0].width = view->width; - state->viewports[0].height = view->height; - state->viewport_count = 1; - wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports); + state->viewport.x = 0; + state->viewport.y = 0; + state->viewport.width = view->width; + state->viewport.height = view->height; + wined3d_cs_emit_set_viewport(device->cs, &state->viewport); - SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height); - state->scissor_rect_count = 1; - wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects); + SetRect(&state->scissor_rect, 0, 0, view->width, view->height); + wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect); } if (device->d3d_initialized) { if (reset_state) hr = wined3d_device_create_primary_opengl_context(device); + swapchain_update_swap_interval(swapchain); } /* All done. There is no need to reload resources or shaders, this will happen automatically on the @@ -5157,49 +5123,55 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso case WINED3D_RTYPE_TEXTURE_3D: for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) { - if (&device->state.textures[i]->resource == resource) + struct wined3d_texture *texture = texture_from_resource(resource); + + if (device->state.textures[i] == texture) { - ERR("Texture resource %p is still in use, stage %u.\n", resource, i); + ERR("Texture %p is still in use, stage %u.\n", texture, i); device->state.textures[i] = NULL; } - if (device->recording && &device->update_state->textures[i]->resource == resource) + if (device->recording && device->update_state->textures[i] == texture) { - ERR("Texture resource %p is still in use by recording stateblock %p, stage %u.\n", - resource, device->recording, i); + ERR("Texture %p is still in use by recording stateblock %p, stage %u.\n", + texture, device->recording, i); device->update_state->textures[i] = NULL; } } break; case WINED3D_RTYPE_BUFFER: - for (i = 0; i < MAX_STREAMS; ++i) { - if (&device->state.streams[i].buffer->resource == resource) + struct wined3d_buffer *buffer = buffer_from_resource(resource); + + for (i = 0; i < MAX_STREAMS; ++i) { - ERR("Buffer resource %p is still in use, stream %u.\n", resource, i); - device->state.streams[i].buffer = NULL; + if (device->state.streams[i].buffer == buffer) + { + ERR("Buffer %p is still in use, stream %u.\n", buffer, i); + device->state.streams[i].buffer = NULL; + } + + if (device->recording && device->update_state->streams[i].buffer == buffer) + { + ERR("Buffer %p is still in use by stateblock %p, stream %u.\n", + buffer, device->recording, i); + device->update_state->streams[i].buffer = NULL; + } } - if (device->recording && &device->update_state->streams[i].buffer->resource == resource) + if (device->state.index_buffer == buffer) { - ERR("Buffer resource %p is still in use by stateblock %p, stream %u.\n", - resource, device->recording, i); - device->update_state->streams[i].buffer = NULL; + ERR("Buffer %p is still in use as index buffer.\n", buffer); + device->state.index_buffer = NULL; } - } - if (&device->state.index_buffer->resource == resource) - { - ERR("Buffer resource %p is still in use as index buffer.\n", resource); - device->state.index_buffer = NULL; - } - - if (device->recording && &device->update_state->index_buffer->resource == resource) - { - ERR("Buffer resource %p is still in use by stateblock %p as index buffer.\n", - resource, device->recording); - device->update_state->index_buffer = NULL; + if (device->recording && device->update_state->index_buffer == buffer) + { + ERR("Buffer %p is still in use by stateblock %p as index buffer.\n", + buffer, device->recording); + device->update_state->index_buffer = NULL; + } } break; @@ -5268,8 +5240,6 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); device->update_state = &device->state; - device->max_frame_latency = 3; - if (!(device->cs = wined3d_cs_create(device))) { WARN("Failed to create command stream.\n"); @@ -5369,3 +5339,58 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL else return CallWindowProcA(proc, window, message, wparam, lparam); } +#if defined(STAGING_CSMT) + +/* Context activation is done by the caller */ +struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage, + GLenum type_hint, struct wined3d_context *context) +{ + struct wined3d_gl_bo *ret; + const struct wined3d_gl_info *gl_info; + + TRACE("device %p, size %u, gl_usage %u, type_hint %u\n", device, size, gl_usage, + type_hint); + + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); + if(!ret) + return NULL; + ret->type_hint = type_hint; + ret->size = size; + ret->usage = gl_usage; + + gl_info = context->gl_info; + + GL_EXTCALL(glGenBuffers(1, &ret->name)); + if (type_hint == GL_ELEMENT_ARRAY_BUFFER) + context_invalidate_state(context, STATE_INDEXBUFFER); + GL_EXTCALL(glBindBuffer(type_hint, ret->name)); + GL_EXTCALL(glBufferData(type_hint, size, NULL, gl_usage)); + GL_EXTCALL(glBindBuffer(type_hint, 0)); + checkGLcall("Create buffer object"); + + TRACE("Successfully created and set up buffer %u\n", ret->name); + return ret; +} + +/* Context activation is done by the caller */ +static void wined3d_device_destroy_bo(struct wined3d_device *device, const struct wined3d_context *context, + struct wined3d_gl_bo *bo) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name); + + GL_EXTCALL(glDeleteBuffers(1, &bo->name)); + checkGLcall("glDeleteBuffers"); + + HeapFree(GetProcessHeap(), 0, bo); +} + +/* Context activation is done by the caller */ +void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, + const struct wined3d_context *context) +{ + TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name); + + wined3d_device_destroy_bo(device, context, bo); +} +#endif /* STAGING_CSMT */ diff --git a/dll/directx/wine/wined3d/directx.c b/dll/directx/wine/wined3d/directx.c index baeb287b5c8..d82a6713434 100644 --- a/dll/directx/wine/wined3d/directx.c +++ b/dll/directx/wine/wined3d/directx.c @@ -156,7 +156,6 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS }, {"GL_ARB_point_sprite", ARB_POINT_SPRITE }, {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX }, - {"GL_ARB_sample_shading", ARB_SAMPLE_SHADING }, {"GL_ARB_sampler_objects", ARB_SAMPLER_OBJECTS }, {"GL_ARB_seamless_cube_map", ARB_SEAMLESS_CUBE_MAP }, {"GL_ARB_shader_atomic_counters", ARB_SHADER_ATOMIC_COUNTERS }, @@ -164,7 +163,6 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_shader_image_load_store", ARB_SHADER_IMAGE_LOAD_STORE }, {"GL_ARB_shader_image_size", ARB_SHADER_IMAGE_SIZE }, {"GL_ARB_shader_storage_buffer_object", ARB_SHADER_STORAGE_BUFFER_OBJECT}, - {"GL_ARB_shader_texture_image_samples", ARB_SHADER_TEXTURE_IMAGE_SAMPLES}, {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD }, {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100 }, {"GL_ARB_shading_language_420pack", ARB_SHADING_LANGUAGE_420PACK }, @@ -203,6 +201,7 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_transform_feedback3", ARB_TRANSFORM_FEEDBACK3 }, {"GL_ARB_uniform_buffer_object", ARB_UNIFORM_BUFFER_OBJECT }, {"GL_ARB_vertex_array_bgra", ARB_VERTEX_ARRAY_BGRA }, + {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND }, {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT }, {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM }, {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER }, @@ -679,7 +678,7 @@ static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, struc GLenum error; DWORD data[16]; - if (!gl_info->supported[EXT_SECONDARY_COLOR] || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) + if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE; while (gl_info->gl_ops.gl.p_glGetError()); @@ -859,8 +858,6 @@ static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, struct w return FALSE; if (!gl_info->supported[ARB_FRAGMENT_PROGRAM]) return FALSE; - if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) - return FALSE; gl_info->gl_ops.gl.p_glGenTextures(1, &tex); gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex); @@ -1401,13 +1398,11 @@ static const struct gpu_description gpu_description_table[] = {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX980, "NVIDIA GeForce GTX 980", DRIVER_NVIDIA_GEFORCE8, 4096}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX980TI, "NVIDIA GeForce GTX 980 Ti", DRIVER_NVIDIA_GEFORCE8, 6144}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1050, "NVIDIA GeForce GTX 1050", DRIVER_NVIDIA_GEFORCE8, 2048}, - {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1050TI, "NVIDIA GeForce GTX 1050 Ti", DRIVER_NVIDIA_GEFORCE8, 4096}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1060, "NVIDIA GeForce GTX 1060", DRIVER_NVIDIA_GEFORCE8, 6144}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1070, "NVIDIA GeForce GTX 1070", DRIVER_NVIDIA_GEFORCE8, 8192}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1080, "NVIDIA GeForce GTX 1080", DRIVER_NVIDIA_GEFORCE8, 8192}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX1080TI, "NVIDIA GeForce GTX 1080 Ti", DRIVER_NVIDIA_GEFORCE8, 11264}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_TITANX_PASCAL, "NVIDIA TITAN X (Pascal)", DRIVER_NVIDIA_GEFORCE8, 12288}, - {HW_VENDOR_NVIDIA, CARD_NVIDIA_TITANV, "NVIDIA TITAN V", DRIVER_NVIDIA_GEFORCE8, 12288}, /* AMD cards */ {HW_VENDOR_AMD, CARD_AMD_RAGE_128PRO, "ATI Rage Fury", DRIVER_AMD_RAGE_128PRO, 16 }, @@ -1708,11 +1703,13 @@ static void init_driver_info(struct wined3d_driver_info *driver_info, * In order to avoid this application bug we limit the amount of video memory * to LONG_MAX for older Windows versions. */ +#ifdef __i386__ if (driver_model < DRIVER_MODEL_NT6X && driver_info->vram_bytes > LONG_MAX) { TRACE("Limiting amount of video memory to %#lx bytes for OS version older than Vista.\n", LONG_MAX); driver_info->vram_bytes = LONG_MAX; } +#endif /* Try to obtain driver version information for the current Windows version. This fails in * some cases: @@ -1906,13 +1903,11 @@ static const struct wined3d_renderer_table cards_nvidia_binary[] = { /* Direct 3D 11 */ - {"TITAN V", CARD_NVIDIA_TITANV}, /* GeForce 1000 - highend */ {"TITAN X (Pascal)", CARD_NVIDIA_TITANX_PASCAL}, /* GeForce 1000 - highend */ {"GTX 1080 Ti", CARD_NVIDIA_GEFORCE_GTX1080TI}, /* GeForce 1000 - highend */ {"GTX 1080", CARD_NVIDIA_GEFORCE_GTX1080}, /* GeForce 1000 - highend */ {"GTX 1070", CARD_NVIDIA_GEFORCE_GTX1070}, /* GeForce 1000 - highend */ {"GTX 1060", CARD_NVIDIA_GEFORCE_GTX1060}, /* GeForce 1000 - midend high */ - {"GTX 1050 Ti", CARD_NVIDIA_GEFORCE_GTX1050TI}, /* GeForce 1000 - midend */ {"GTX 1050", CARD_NVIDIA_GEFORCE_GTX1050}, /* GeForce 1000 - midend */ {"GTX 980 Ti", CARD_NVIDIA_GEFORCE_GTX980TI}, /* GeForce 900 - highend */ {"GTX 980", CARD_NVIDIA_GEFORCE_GTX980}, /* GeForce 900 - highend */ @@ -2230,7 +2225,9 @@ cards_intel[] = {"830M", CARD_INTEL_830M}, }, /* 20101109 - These are never returned by current Gallium radeon - * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351. */ + * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351. + * + * These are returned but not handled: RC410, RV380. */ cards_amd_mesa[] = { /* Polaris 10/11 */ @@ -2308,12 +2305,10 @@ cards_amd_mesa[] = {"RS482", CARD_AMD_RADEON_XPRESS_200M}, {"RS480", CARD_AMD_RADEON_XPRESS_200M}, {"RS400", CARD_AMD_RADEON_XPRESS_200M}, - {"RC410", CARD_AMD_RADEON_XPRESS_200M}, /* R300 */ {"R360", CARD_AMD_RADEON_9500}, {"R350", CARD_AMD_RADEON_9500}, {"R300", CARD_AMD_RADEON_9500}, - {"RV380", CARD_AMD_RADEON_9500}, {"RV370", CARD_AMD_RADEON_9500}, {"RV360", CARD_AMD_RADEON_9500}, {"RV351", CARD_AMD_RADEON_9500}, @@ -2827,8 +2822,6 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glPointParameterfvARB) /* GL_ARB_provoking_vertex */ USE_GL_FUNC(glProvokingVertex) - /* GL_ARB_sample_shading */ - USE_GL_FUNC(glMinSampleShadingARB) /* GL_ARB_sampler_objects */ USE_GL_FUNC(glGenSamplers) USE_GL_FUNC(glDeleteSamplers) @@ -2955,6 +2948,17 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glGetUniformBlockIndex) USE_GL_FUNC(glGetUniformIndices) USE_GL_FUNC(glUniformBlockBinding) + /* GL_ARB_vertex_blend */ + USE_GL_FUNC(glVertexBlendARB) + USE_GL_FUNC(glWeightPointerARB) + USE_GL_FUNC(glWeightbvARB) + USE_GL_FUNC(glWeightdvARB) + USE_GL_FUNC(glWeightfvARB) + USE_GL_FUNC(glWeightivARB) + USE_GL_FUNC(glWeightsvARB) + USE_GL_FUNC(glWeightubvARB) + USE_GL_FUNC(glWeightuivARB) + USE_GL_FUNC(glWeightusvARB) /* GL_ARB_vertex_buffer_object */ USE_GL_FUNC(glBindBufferARB) USE_GL_FUNC(glBufferDataARB) @@ -3422,7 +3426,6 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) MAP_GL_FUNCTION(glIsEnabledi, glIsEnabledIndexedEXT); MAP_GL_FUNCTION(glLinkProgram, glLinkProgramARB); MAP_GL_FUNCTION(glMapBuffer, glMapBufferARB); - MAP_GL_FUNCTION(glMinSampleShading, glMinSampleShadingARB); MAP_GL_FUNCTION_CAST(glShaderSource, glShaderSourceARB); MAP_GL_FUNCTION(glTexBuffer, glTexBufferARB); MAP_GL_FUNCTION_CAST(glTexImage3D, glTexImage3DEXT); @@ -3476,6 +3479,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info) GLfloat gl_floatv[2]; GLint gl_max; + gl_info->limits.blends = 1; gl_info->limits.buffers = 1; gl_info->limits.textures = 0; gl_info->limits.texture_coords = 0; @@ -3631,6 +3635,12 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info) gl_info->limits.texture_coords = 1; } + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max); + gl_info->limits.blends = gl_max; + TRACE("Max blends: %u.\n", gl_info->limits.blends); + } if (gl_info->supported[EXT_TEXTURE3D]) { gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max); @@ -3900,7 +3910,6 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, {EXT_TEXTURE_SNORM, MAKEDWORD_VERSION(3, 1)}, /* We don't need or want GL_ARB_texture_rectangle (core in 3.1). */ - {ARB_DEPTH_CLAMP, MAKEDWORD_VERSION(3, 2)}, {ARB_DRAW_ELEMENTS_BASE_VERTEX, MAKEDWORD_VERSION(3, 2)}, /* ARB_geometry_shader4 exposes a somewhat different API compared to 3.2 * core geometry shaders so it's not really correct to expose the @@ -3924,7 +3933,6 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, {ARB_DRAW_INDIRECT, MAKEDWORD_VERSION(4, 0)}, {ARB_GPU_SHADER5, MAKEDWORD_VERSION(4, 0)}, - {ARB_SAMPLE_SHADING, MAKEDWORD_VERSION(4, 0)}, {ARB_TESSELLATION_SHADER, MAKEDWORD_VERSION(4, 0)}, {ARB_TEXTURE_CUBE_MAP_ARRAY, MAKEDWORD_VERSION(4, 0)}, {ARB_TEXTURE_GATHER, MAKEDWORD_VERSION(4, 0)}, @@ -3966,7 +3974,6 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, {ARB_CLIP_CONTROL, MAKEDWORD_VERSION(4, 5)}, {ARB_CULL_DISTANCE, MAKEDWORD_VERSION(4, 5)}, {ARB_DERIVATIVE_CONTROL, MAKEDWORD_VERSION(4, 5)}, - {ARB_SHADER_TEXTURE_IMAGE_SAMPLES, MAKEDWORD_VERSION(4, 5)}, {ARB_PIPELINE_STATISTICS_QUERY, MAKEDWORD_VERSION(4, 6)}, {ARB_TEXTURE_FILTER_ANISOTROPIC, MAKEDWORD_VERSION(4, 6)}, @@ -4080,11 +4087,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, gl_info->supported[WINED3D_GL_BLEND_EQUATION] = TRUE; if (gl_version >= MAKEDWORD_VERSION(2, 0)) - { gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE; - /* We want to use the core APIs for two-sided stencil in GL 2.0. */ - gl_info->supported[EXT_STENCIL_TWO_SIDE] = FALSE; - } if (gl_version >= MAKEDWORD_VERSION(3, 2)) gl_info->supported[WINED3D_GL_VERSION_3_2] = TRUE; @@ -5357,7 +5360,7 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad case WINED3D_RTYPE_NONE: allowed_usage = WINED3DUSAGE_DEPTHSTENCIL | WINED3DUSAGE_RENDERTARGET; - gl_type = WINED3D_GL_RES_TYPE_TEX_2D; + gl_type = WINED3D_GL_RES_TYPE_TEX_1D; gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D; break; @@ -5366,7 +5369,6 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad | WINED3DUSAGE_SOFTWAREPROCESSING | WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_FILTER - | WINED3DUSAGE_QUERY_GENMIPMAP | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING | WINED3DUSAGE_QUERY_SRGBREAD | WINED3DUSAGE_QUERY_SRGBWRITE @@ -5431,6 +5433,12 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D; break; + case WINED3D_RTYPE_BUFFER: + allowed_usage = WINED3DUSAGE_DYNAMIC + | WINED3DUSAGE_QUERY_VERTEXTEXTURE; + gl_type = gl_type_end = WINED3D_GL_RES_TYPE_BUFFER; + break; + default: FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type)); return WINED3DERR_NOTAVAILABLE; @@ -5679,6 +5687,9 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte WINED3DCAPS3_COPY_TO_VIDMEM | WINED3DCAPS3_COPY_TO_SYSTEMMEM; + caps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE | + WINED3DPRESENT_INTERVAL_ONE; + caps->CursorCaps = WINED3DCURSORCAPS_COLOR | WINED3DCURSORCAPS_LOWRES; @@ -6608,16 +6619,28 @@ static DWORD get_max_gl_version(const struct wined3d_gl_info *gl_info, DWORD fla { const char *gl_vendor, *gl_renderer; - if (wined3d_settings.explicit_gl_version) + if (wined3d_settings.explicit_gl_version || (flags & WINED3D_PIXEL_CENTER_INTEGER)) return wined3d_settings.max_gl_version; gl_vendor = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_VENDOR); gl_renderer = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_RENDERER); if (!gl_vendor || !gl_renderer || wined3d_guess_card_vendor(gl_vendor, gl_renderer) == HW_VENDOR_NVIDIA) - return MAKEDWORD_VERSION(1, 0); + return wined3d_settings.max_gl_version; - return wined3d_settings.max_gl_version; + return MAKEDWORD_VERSION(4, 4); +} + +static BOOL has_extension(const char *list, const char *ext) +{ + size_t len = strlen(ext); + while (list) + { + while (*list == ' ') list++; + if (!strncmp(list, ext, len) && (!list[len] || list[len] == ' ')) return TRUE; + list = strchr(list, ' '); + } + return FALSE; } static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, DWORD wined3d_creation_flags) @@ -6678,6 +6701,17 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, } max_gl_version = get_max_gl_version(gl_info, wined3d_creation_flags); + + if (wined3d_creation_flags & WINED3D_REQUEST_D3D10) + { + const char *gl_extensions = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_EXTENSIONS); + if (!has_extension(gl_extensions, "GL_ARB_compatibility")) + { + ERR_(winediag)("GL_ARB_compatibility not supported, requesting context with GL version 3.2.\n"); + max_gl_version = MAKEDWORD_VERSION(3, 2); + } + } + for (i = 0; i < ARRAY_SIZE(supported_gl_versions); ++i) { if (supported_gl_versions[i] <= max_gl_version) diff --git a/dll/directx/wine/wined3d/glsl_shader.c b/dll/directx/wine/wined3d/glsl_shader.c index 41bd1fd0552..4c879f9fc5e 100644 --- a/dll/directx/wine/wined3d/glsl_shader.c +++ b/dll/directx/wine/wined3d/glsl_shader.c @@ -91,6 +91,7 @@ struct glsl_sample_function enum wined3d_data_type data_type; BOOL output_single_component; unsigned int offset_size; + enum wined3d_shader_resource_type emulate_lod; }; enum heap_node_op @@ -804,12 +805,11 @@ static void append_transform_feedback_skip_components(const char **varyings, } } -static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc, +static void shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc, struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count, char *strings, unsigned int *strings_length, GLenum buffer_mode) { unsigned int i, buffer_idx, count, length, highest_output_slot, stride; - BOOL have_varyings_to_record = FALSE; count = length = 0; highest_output_slot = 0; @@ -859,8 +859,6 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3 string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx); append_transform_feedback_varying(varyings, &count, &strings, &length, buffer); } - - have_varyings_to_record = TRUE; } if (buffer_idx < so_desc->buffer_stride_count @@ -885,12 +883,10 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3 *varying_count = count; if (strings_length) *strings_length = length; - - return have_varyings_to_record; } static void shader_glsl_init_transform_feedback(const struct wined3d_context *context, - struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader) + struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader) { const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; const struct wined3d_gl_info *gl_info = context->gl_info; @@ -946,13 +942,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co buffer = string_buffer_get(&priv->string_buffers); - if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode)) - { - FIXME("No varyings to record, disabling transform feedback.\n"); - shader->u.gs.so_desc.element_count = 0; - string_buffer_release(&priv->string_buffers, buffer); - return; - } + shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode); if (!(varyings = heap_calloc(count, sizeof(*varyings)))) { @@ -1470,7 +1460,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_glsl_priv *priv = shader_priv; - float position_fixup[4 * WINED3D_MAX_VIEWPORTS]; + float position_fixup[4]; float normal[3 * 3]; DWORD update_mask; @@ -1508,11 +1498,9 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP) { - unsigned int fixup_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? - max(state->viewport_count, 1) : 1; - shader_get_position_fixup(context, state, fixup_count, position_fixup); + shader_get_position_fixup(context, state, position_fixup); if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) - GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, fixup_count, position_fixup)); + GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup)); else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup)); else @@ -1969,11 +1957,6 @@ static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_ } } -static const char *get_fragment_output(const struct wined3d_gl_info *gl_info) -{ - return needs_legacy_glsl_syntax(gl_info) ? "gl_FragData" : "ps_out"; -} - static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) { switch (primitive_type) @@ -2956,10 +2939,6 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * sprintf(register_name, "vpc[%u]", reg->idx[0].offset); break; - case WINED3DSPR_SAMPLEMASK: - sprintf(register_name, "sample_mask"); - break; - default: FIXME("Unhandled register type %#x.\n", reg->type); sprintf(register_name, "unrecognized_register"); @@ -3264,6 +3243,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type; struct shader_glsl_ctx_priv *priv = ctx->backend_data; const struct wined3d_gl_info *gl_info = ctx->gl_info; + BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx); BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED; BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL @@ -3276,6 +3256,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context unsigned int coord_size, deriv_size; sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type; + sample_function->emulate_lod = WINED3D_SHADER_RESOURCE_NONE; if (resource_type >= ARRAY_SIZE(resource_type_info)) { @@ -3287,7 +3268,30 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) projected = FALSE; - if (needs_legacy_glsl_syntax(gl_info)) + if (shadow && lod) + { + switch (resource_type) + { + /* emulate textureLod(sampler2DArrayShadow, ...) using textureGradOffset */ + case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: + sample_function->emulate_lod = resource_type; + grad = offset = TRUE; + lod = FALSE; + break; + + /* emulate textureLod(samplerCubeShadow, ...) using shadowCubeGrad */ + case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: + sample_function->emulate_lod = resource_type; + grad = legacy_syntax = TRUE; + lod = FALSE; + break; + + default: + break; + } + } + + if (legacy_syntax) { if (shadow) base = "shadow"; @@ -3327,7 +3331,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context sample_function->offset_size = offset ? deriv_size : 0; sample_function->coord_mask = (1u << coord_size) - 1; sample_function->deriv_mask = (1u << deriv_size) - 1; - sample_function->output_single_component = shadow && !needs_legacy_glsl_syntax(gl_info); + sample_function->output_single_component = shadow && !legacy_syntax; } static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx, @@ -3448,6 +3452,7 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_ const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset, const char *coord_reg_fmt, ...) { + static const struct wined3d_shader_texel_offset dummy_offset = {0, 0, 0}; const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; char dst_swizzle[6]; struct color_fixup_desc fixup; @@ -3516,6 +3521,26 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_ break; } } + if (sample_function->emulate_lod) + { + if (strcmp(bias, "0")) FIXME("Don't know how to emulate lod level %s\n", bias); + switch (sample_function->emulate_lod) + { + case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: + if (!dx) dx = "vec2(0.0, 0.0)"; + if (!dy) dy = "vec2(0.0, 0.0)"; + break; + + case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: + if (!dx) dx = "vec3(0.0, 0.0, 0.0)"; + if (!dy) dy = "vec3(0.0, 0.0, 0.0)"; + break; + + default: + break; + } + if (!offset) offset = &dummy_offset; + } if (dx && dy) shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy); else if (bias) @@ -3537,7 +3562,7 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_ shader_glsl_color_correction(ins, fixup); } -static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOOL use_viewport_index) +static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer) { /* Write the final position. * @@ -3546,16 +3571,8 @@ static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOO * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow * a MAD. */ - if (use_viewport_index) - { - shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup[gl_ViewportIndex].y;\n"); - shader_addline(buffer, "gl_Position.xy += pos_fixup[gl_ViewportIndex].zw * gl_Position.ww;\n"); - } - else - { - shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n"); - shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n"); - } + shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n"); + shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n"); /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix() * in utils.c @@ -4881,11 +4898,10 @@ static void shader_glsl_else(const struct wined3d_shader_instruction *ins) static void shader_glsl_emit(const struct wined3d_shader_instruction *ins) { unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset; - const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n"); if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL]) - shader_glsl_fixup_position(ins->ctx->buffer, reg_maps->viewport_array); + shader_glsl_fixup_position(ins->ctx->buffer); if (!stream) shader_addline(ins->ctx->buffer, "EmitVertex();\n"); @@ -5740,71 +5756,6 @@ static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins) shader_addline(buffer, ")%s);\n", dst_swizzle); } -static void shader_glsl_sample_info(const struct wined3d_shader_instruction *ins) -{ - const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; - struct wined3d_string_buffer *buffer = ins->ctx->buffer; - const struct wined3d_shader_dst_param *dst = ins->dst; - const struct wined3d_shader_src_param *src = ins->src; - enum wined3d_shader_resource_type resource_type; - enum wined3d_data_type dst_data_type; - unsigned int resource_idx, bind_idx; - char dst_swizzle[6]; - DWORD write_mask; - - dst_data_type = dst->reg.data_type; - if (ins->flags == WINED3DSI_SAMPLE_INFO_UINT) - dst_data_type = WINED3D_DATA_UINT; - else if (ins->flags) - FIXME("Unhandled flags %#x.\n", ins->flags); - - write_mask = shader_glsl_append_dst_ext(buffer, ins, dst, dst_data_type); - shader_glsl_get_swizzle(src, FALSE, write_mask, dst_swizzle); - - if (dst_data_type == WINED3D_DATA_UINT) - shader_addline(buffer, "uvec4("); - else - shader_addline(buffer, "vec4("); - - if (src->reg.type == WINED3DSPR_RASTERIZER) - { - if (gl_info->supported[ARB_SAMPLE_SHADING]) - { - shader_addline(buffer, "gl_NumSamples"); - } - else - { - FIXME("OpenGL implementation does not support ARB_sample_shading.\n"); - shader_addline(buffer, "1"); - } - } - else - { - resource_idx = src->reg.idx[0].offset; - resource_type = reg_maps->resource_info[resource_idx].type; - if (resource_type >= ARRAY_SIZE(resource_type_info)) - { - ERR("Unexpected resource type %#x.\n", resource_type); - return; - } - bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT); - - if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES]) - { - shader_addline(buffer, "textureSamples(%s_sampler%u)", - shader_glsl_get_prefix(reg_maps->shader_version.type), bind_idx); - } - else - { - FIXME("textureSamples() is not supported.\n"); - shader_addline(buffer, "1"); - } - } - - shader_addline(buffer, ", 0, 0, 0)%s);\n", dst_swizzle); -} - static void shader_glsl_ld(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; @@ -6547,7 +6498,7 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w semantic_idx = input->semantic_idx; shader_glsl_write_mask_to_str(input->mask, reg_mask); - if (args->vp_mode == WINED3D_VP_MODE_SHADER) + if (args->vp_mode == vertexshader) { if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx) { @@ -6563,14 +6514,6 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n", input->register_idx, reg_mask); } - else if (input->sysval_semantic == WINED3D_SV_SAMPLE_INDEX) - { - if (gl_info->supported[ARB_SAMPLE_SHADING]) - shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_SampleID);\n", - input->register_idx, reg_mask); - else - FIXME("ARB_sample_shading is not supported.\n"); - } else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx) { if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) @@ -6579,14 +6522,6 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w else FIXME("ARB_fragment_layer_viewport is not supported.\n"); } - else if (input->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) - { - if (gl_info->supported[ARB_VIEWPORT_ARRAY]) - shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_ViewportIndex);\n", - input->register_idx, reg_mask); - else - FIXME("ARB_viewport_array is not supported.\n"); - } else { if (input->sysval_semantic) @@ -6602,7 +6537,7 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w if (args->pointsprite) shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", shader->u.ps.input_reg_map[input->register_idx]); - else if (args->vp_mode == WINED3D_VP_MODE_NONE && args->texcoords_initialized & (1u << semantic_idx)) + else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx)) shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n", shader->u.ps.input_reg_map[input->register_idx], reg_mask, needs_legacy_glsl_syntax(gl_info) @@ -6878,11 +6813,6 @@ static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n", output->register_idx, reg_mask); } - else if (output->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) - { - shader_addline(buffer, "gl_ViewportIndex = floatBitsToInt(outputs[%u])%s;\n", - output->register_idx, reg_mask); - } else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) { shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask); @@ -7307,8 +7237,6 @@ static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer, shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n"); if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT]) shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); - if (gl_info->supported[ARB_SHADER_TEXTURE_IMAGE_SAMPLES]) - shader_addline(buffer, "#extension GL_ARB_shader_texture_image_samples : enable\n"); if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]) @@ -7321,8 +7249,6 @@ static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer, shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n"); if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT]) shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n"); - if (gl_info->supported[ARB_VIEWPORT_ARRAY]) - shader_addline(buffer, "#extension GL_ARB_viewport_array : enable\n"); if (gl_info->supported[EXT_GPU_SHADER4]) shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n"); if (gl_info->supported[EXT_TEXTURE_ARRAY]) @@ -7348,9 +7274,6 @@ static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_in shader_glsl_generate_fog_code(buffer, gl_info, args->fog); shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1); - - if (reg_maps->sample_mask) - shader_addline(buffer, "gl_SampleMask[0] = floatBitsToInt(sample_mask);\n"); } /* Context activation is done by the caller. */ @@ -7387,8 +7310,6 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n"); if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n"); - if (gl_info->supported[ARB_SAMPLE_SHADING]) - shader_addline(buffer, "#extension GL_ARB_sample_shading : enable\n"); if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n"); /* The spec says that it doesn't have to be explicitly enabled, but the @@ -7441,7 +7362,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts); } - if (version->major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER) + if (version->major < 3 || args->vp_mode != vertexshader) { shader_addline(buffer, "uniform struct\n{\n"); shader_addline(buffer, " vec4 color;\n"); @@ -7475,7 +7396,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context { unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input); - if (args->vp_mode == WINED3D_VP_MODE_SHADER && reg_maps->input_registers) + if (args->vp_mode == vertexshader && reg_maps->input_registers) shader_glsl_declare_shader_inputs(gl_info, buffer, in_count, shader->u.ps.interpolation_mode, version->major >= 4); shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count); @@ -7561,9 +7482,6 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context shader_addline(buffer, "void main()\n{\n"); - if (reg_maps->sample_mask) - shader_addline(buffer, "float sample_mask = uintBitsToFloat(0xffffffffu);\n"); - /* Direct3D applications expect integer vPos values, while OpenGL drivers * add approximately 0.5. This causes off-by-one problems as spotted by * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly @@ -7592,7 +7510,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n"); } - if (reg_maps->shader_version.major < 3 || args->vp_mode != WINED3D_VP_MODE_SHADER) + if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader) { unsigned int i; WORD map = reg_maps->texcoord; @@ -7686,7 +7604,7 @@ static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_in shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n"); if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) - shader_glsl_fixup_position(buffer, FALSE); + shader_glsl_fixup_position(buffer); } /* Context activation is done by the caller. */ @@ -7924,7 +7842,7 @@ static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_in shader_addline(buffer, "setup_ds_output(ds_out);\n"); if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) - shader_glsl_fixup_position(buffer, FALSE); + shader_glsl_fixup_position(buffer); } static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context, @@ -8028,11 +7946,7 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; struct wined3d_string_buffer *buffer = &priv->shader_buffer; const struct wined3d_gl_info *gl_info = context->gl_info; - const struct wined3d_shader_signature_element *output; - enum wined3d_primitive_type primitive_type; struct shader_glsl_ctx_priv priv_ctx; - unsigned int max_vertices; - unsigned int i, j; GLuint shader_id; memset(&priv_ctx, 0, sizeof(priv_ctx)); @@ -8044,42 +7958,16 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); - primitive_type = shader->u.gs.input_type ? shader->u.gs.input_type : args->primitive_type; - shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(primitive_type)); + shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(shader->u.gs.input_type)); if (shader->u.gs.instance_count > 1) shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count); shader_addline(buffer, ") in;\n"); - - primitive_type = shader->u.gs.output_type ? shader->u.gs.output_type : args->primitive_type; - if (!(max_vertices = shader->u.gs.vertices_out)) - { - switch (args->primitive_type) - { - case WINED3D_PT_POINTLIST: - max_vertices = 1; - break; - case WINED3D_PT_LINELIST: - max_vertices = 2; - break; - case WINED3D_PT_TRIANGLELIST: - max_vertices = 3; - break; - default: - FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(args->primitive_type)); - break; - } - } shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n", - glsl_primitive_type_from_d3d(primitive_type), max_vertices); + glsl_primitive_type_from_d3d(shader->u.gs.output_type), shader->u.gs.vertices_out); shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); if (!gl_info->supported[ARB_CLIP_CONTROL]) - { - shader_addline(buffer, "uniform vec4 pos_fixup"); - if (reg_maps->viewport_array) - shader_addline(buffer, "[%u]", WINED3D_MAX_VIEWPORTS); - shader_addline(buffer, ";\n"); - } + shader_addline(buffer, "uniform vec4 pos_fixup;\n"); if (is_rasterization_disabled(shader)) { @@ -8090,29 +7978,9 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info, TRUE, args->interpolation_mode); } - shader_addline(buffer, "void main()\n{\n"); - if (shader->function) - { - if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) - return 0; - } - else - { - for (i = 0; i < max_vertices; ++i) - { - for (j = 0; j < shader->output_signature.element_count; ++j) - { - output = &shader->output_signature.elements[j]; - shader_addline(buffer, "gs_out[%u] = shader_in[%u].reg[%u];\n", - output->register_idx, i, output->register_idx); - } - shader_addline(buffer, "setup_gs_output(gs_out);\n"); - if (!gl_info->supported[ARB_CLIP_CONTROL]) - shader_glsl_fixup_position(buffer, FALSE); - shader_addline(buffer, "EmitVertex();\n"); - } - } + if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) + return 0; shader_addline(buffer, "}\n"); shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); @@ -9042,7 +8910,7 @@ static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buf } static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color, - BOOL alpha, BOOL tmp_dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) + BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) { const char *dstmask, *dstreg, *arg0, *arg1, *arg2; @@ -9053,7 +8921,10 @@ static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, un else dstmask = ".w"; - dstreg = tmp_dst ? "temp_reg" : "ret"; + if (dst == tempreg) + dstreg = "temp_reg"; + else + dstreg = "ret"; arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0); arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1); @@ -9223,7 +9094,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * tfactor_used = TRUE; if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) tempreg_used = TRUE; - if (settings->op[stage].tmp_dst) + if (settings->op[stage].dst == tempreg) tempreg_used = TRUE; if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT) tss_const_map |= 1u << stage; @@ -9419,12 +9290,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * if (!(tex_map & (1u << stage))) continue; - if (settings->op[stage].projected == WINED3D_PROJECTION_NONE) + if (settings->op[stage].projected == proj_none) { proj = FALSE; } - else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4 - || settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) + else if (settings->op[stage].projected == proj_count4 + || settings->op[stage].projected == proj_count3) { proj = TRUE; } @@ -9507,12 +9378,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1); /* With projective textures, texbem only divides the static - * texture coordinate, not the displacement, so multiply the + * texture coord, 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 != proj_none) { - if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4) + if (settings->op[stage].projected == proj_count4) { shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n", stage, stage); @@ -9537,7 +9408,7 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n", stage, stage - 1, stage - 1, stage - 1); } - else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) + else if (settings->op[stage].projected == proj_count3) { shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n", stage, texture_function, stage, stage); @@ -9589,23 +9460,23 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * if (settings->op[stage].aop == WINED3D_TOP_DISABLE) { - shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, + shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst, settings->op[stage].cop, settings->op[stage].carg0, settings->op[stage].carg1, settings->op[stage].carg2); } else if (op_equal) { - shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].tmp_dst, + shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].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) { - shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, + shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst, settings->op[stage].cop, settings->op[stage].carg0, settings->op[stage].carg1, settings->op[stage].carg2); - shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].tmp_dst, + shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].dst, settings->op[stage].aop, settings->op[stage].aarg0, settings->op[stage].aarg1, settings->op[stage].aarg2); } @@ -10905,7 +10776,6 @@ static unsigned int shader_glsl_get_shader_model(const struct wined3d_gl_info *g && gl_info->supported[ARB_SHADER_IMAGE_SIZE] && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING] && gl_info->supported[ARB_TESSELLATION_SHADER] - && gl_info->supported[ARB_TEXTURE_COMPRESSION_BPTC] && gl_info->supported[ARB_TEXTURE_GATHER] && gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) return 5; @@ -11163,7 +11033,7 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB /* WINED3DSIH_SAMPLE_C */ shader_glsl_sample_c, /* WINED3DSIH_SAMPLE_C_LZ */ shader_glsl_sample_c, /* WINED3DSIH_SAMPLE_GRAD */ shader_glsl_sample, - /* WINED3DSIH_SAMPLE_INFO */ shader_glsl_sample_info, + /* WINED3DSIH_SAMPLE_INFO */ NULL, /* WINED3DSIH_SAMPLE_LOD */ shader_glsl_sample, /* WINED3DSIH_SAMPLE_POS */ NULL, /* WINED3DSIH_SETP */ NULL, @@ -12108,854 +11978,3 @@ const struct fragment_pipeline glsl_fragment_pipe = shader_glsl_color_fixup_supported, glsl_fragment_pipe_state_template, }; - -struct glsl_blitter_args -{ - GLenum texture_type; - struct color_fixup_desc fixup; - unsigned short padding; -}; - -struct glsl_blitter_program -{ - struct wine_rb_entry entry; - struct glsl_blitter_args args; - GLuint id; -}; - -struct wined3d_glsl_blitter -{ - struct wined3d_blitter blitter; - struct wined3d_string_buffer_list string_buffers; - struct wine_rb_tree programs; - GLuint palette_texture; -}; - -static int glsl_blitter_args_compare(const void *key, const struct wine_rb_entry *entry) -{ - const struct glsl_blitter_args *a = key; - const struct glsl_blitter_args *b = &WINE_RB_ENTRY_VALUE(entry, const struct glsl_blitter_program, entry)->args; - - return memcmp(a, b, sizeof(*a)); -} - -/* Context activation is done by the caller. */ -static void glsl_free_blitter_program(struct wine_rb_entry *entry, void *ctx) -{ - struct glsl_blitter_program *program = WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry); - struct wined3d_context *context = ctx; - const struct wined3d_gl_info *gl_info = context->gl_info; - - GL_EXTCALL(glDeleteProgram(program->id)); - checkGLcall("glDeleteProgram()"); - heap_free(program); -} - -/* Context activation is done by the caller. */ -static void glsl_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_glsl_blitter *glsl_blitter; - struct wined3d_blitter *next; - - if ((next = blitter->next)) - next->ops->blitter_destroy(next, context); - - glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); - - if (glsl_blitter->palette_texture) - gl_info->gl_ops.gl.p_glDeleteTextures(1, &glsl_blitter->palette_texture); - - wine_rb_destroy(&glsl_blitter->programs, glsl_free_blitter_program, context); - string_buffer_list_cleanup(&glsl_blitter->string_buffers); - - heap_free(glsl_blitter); -} - -static void glsl_blitter_generate_p8_shader(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, - const char *output, const char *tex_type, const char *swizzle) -{ - shader_addline(buffer, "uniform sampler1D sampler_palette;\n"); - shader_addline(buffer, "\nvoid main()\n{\n"); - /* The alpha-component contains the palette index. */ - shader_addline(buffer, " float index = texture%s(sampler, out_texcoord.%s).%c;\n", - needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle, - gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'); - /* Scale the index by 255/256 and add a bias of 0.5 in order to sample in - * the middle. */ - shader_addline(buffer, " index = (index * 255.0 + 0.5) / 256.0;\n"); - shader_addline(buffer, " %s = texture%s(sampler_palette, index);\n", - output, needs_legacy_glsl_syntax(gl_info) ? "1D" : ""); - shader_addline(buffer, "}\n"); -} - -static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, - const char *tex_type) -{ - enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); - char chroma, luminance; - const char *tex; - - /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit - * macropixel, giving effectively 16 bits per pixel. The color consists of - * a luminance(Y) and two chroma(U and V) values. Each macropixel has two - * luminance values, one for each single pixel it contains, and one U and - * one V value shared between both pixels. - * - * The data is loaded into an A8L8 texture. With YUY2, the luminance - * component contains the luminance and alpha the chroma. With UYVY it is - * vice versa. Thus take the format into account when generating the read - * swizzles - * - * Reading the Y value is straightforward - just sample the texture. The - * hardware takes care of filtering in the horizontal and vertical - * direction. - * - * Reading the U and V values is harder. We have to avoid filtering - * horizontally, because that would mix the U and V values of one pixel or - * two adjacent pixels. Thus floor the texture coordinate and add 0.5 to - * get an unfiltered read, regardless of the filtering setting. Vertical - * filtering works automatically though - the U and V values of two rows - * are mixed nicely. - * - * Apart of avoiding filtering issues, the code has to know which value it - * just read, and where it can find the other one. To determine this, it - * checks if it sampled an even or odd pixel, and shifts the 2nd read - * accordingly. - * - * Handling horizontal filtering of U and V values requires reading a 2nd - * pair of pixels, extracting U and V and mixing them. This is not - * implemented yet. - * - * An alternative implementation idea is to load the texture as A8R8G8B8 - * texture, with width / 2. This way one read gives all 3 values, finding - * U and V is easy in an unfiltered situation. Finding the luminance on - * the other hand requires finding out if it is an odd or even pixel. The - * real drawback of this approach is filtering. This would have to be - * emulated completely in the shader, reading up two 2 packed pixels in up - * to 2 rows and interpolating both horizontally and vertically. Beyond - * that it would require adjustments to the texture handling code to deal - * with the width scaling. */ - - if (complex_fixup == COMPLEX_FIXUP_UYVY) - { - chroma = 'x'; - luminance = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y'; - } - else - { - chroma = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'y'; - luminance = 'x'; - } - - tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; - - /* First we have to read the chroma values. This means we need at least - * two pixels (no filtering), or 4 pixels (with filtering). To get the - * unmodified chroma, we have to rid ourselves of the filtering when we - * sample the texture. */ - shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); - /* We must not allow filtering between pixel x and x+1, this would mix U - * and V. Vertical filtering is ok. However, bear in mind that the pixel - * center is at 0.5, so add 0.5. */ - shader_addline(buffer, " texcoord.x = (floor(texcoord.x * size.x) + 0.5) / size.x;\n"); - shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma); - - /* Multiply the x coordinate by 0.5 and get the fraction. This gives 0.25 - * and 0.75 for the even and odd pixels respectively. */ - /* Put the value into either of the chroma values. */ - shader_addline(buffer, " bool even = fract(texcoord.x * size.x * 0.5) < 0.5;\n"); - shader_addline(buffer, " if (even)\n"); - shader_addline(buffer, " chroma.y = luminance;\n"); - shader_addline(buffer, " else\n"); - shader_addline(buffer, " chroma.x = luminance;\n"); - - /* Sample pixel 2. If we read an even pixel, sample the pixel right to the - * current one. Otherwise, sample the left pixel. */ - shader_addline(buffer, " texcoord.x += even ? 1.0 / size.x : -1.0 / size.x;\n"); - shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, chroma); - - /* Put the value into the other chroma. */ - shader_addline(buffer, " if (even)\n"); - shader_addline(buffer, " chroma.x = luminance;\n"); - shader_addline(buffer, " else\n"); - shader_addline(buffer, " chroma.y = luminance;\n"); - - /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of - * the current one and lerp the two U and V values. */ - - /* This gives the correctly filtered luminance value. */ - shader_addline(buffer, " luminance = texture%s(sampler, out_texcoord.xy).%c;\n", tex, luminance); -} - -static void gen_yv12_read(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const char *tex_type) -{ - char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'; - const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; - - /* YV12 surfaces contain a WxH sized luminance plane, followed by a - * (W/2)x(H/2) V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So - * the effective bitdepth is 12 bits per pixel. Since the U and V planes - * have only half the pitch of the luminance plane, the packing into the - * gl texture is a bit unfortunate. If the whole texture is interpreted as - * luminance data it looks approximately like this: - * - * +----------------------------------+---- - * | | - * | | - * | | - * | | - * | | 2 - * | LUMINANCE | - - * | | 3 - * | | - * | | - * | | - * | | - * +----------------+-----------------+---- - * | | | - * | V even rows | V odd rows | - * | | | 1 - * +----------------+------------------ - - * | | | 3 - * | U even rows | U odd rows | - * | | | - * +----------------+-----------------+---- - * | | | - * | 0.5 | 0.5 | - * - * So it appears as if there are 4 chroma images, but in fact the odd rows - * in the chroma images are in the same row as the even ones. So it is - * kinda tricky to read. */ - - /* First sample the chroma values. */ - shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); - /* The chroma planes have only half the width. */ - shader_addline(buffer, " texcoord.x *= 0.5;\n"); - - /* The first value is between 2/3 and 5/6 of the texture's height, so - * scale+bias the coordinate. Also read the right side of the image when - * reading odd lines. - * - * Don't forget to clamp the y values in into the range, otherwise we'll - * get filtering bleeding. */ - - /* Read odd lines from the right side (add 0.5 to the x coordinate). */ - shader_addline(buffer, " if (fract(floor(texcoord.y * size.y) * 0.5 + 1.0 / 6.0) >= 0.5)\n"); - shader_addline(buffer, " texcoord.x += 0.5;\n"); - - /* Clamp, keep the half pixel origin in mind. */ - shader_addline(buffer, " texcoord.y = clamp(2.0 / 3.0 + texcoord.y / 6.0, " - "2.0 / 3.0 + 0.5 / size.y, 5.0 / 6.0 - 0.5 / size.y);\n"); - - shader_addline(buffer, " chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component); - - /* The other chroma value is 1/6th of the texture lower, from 5/6th to - * 6/6th No need to clamp because we're just reusing the already clamped - * value from above. */ - shader_addline(buffer, " texcoord.y += 1.0 / 6.0;\n"); - shader_addline(buffer, " chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component); - - /* Sample the luminance value. It is in the top 2/3rd of the texture, so - * scale the y coordinate. Clamp the y coordinate to prevent the chroma - * values from bleeding into the sampled luminance values due to - * filtering. */ - shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); - /* Multiply the y coordinate by 2/3 and clamp it. */ - shader_addline(buffer, " texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n"); - shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component); -} - -static void gen_nv12_read(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const char *tex_type) -{ - char component = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? 'w' : 'x'; - const char *tex = needs_legacy_glsl_syntax(gl_info) ? tex_type : ""; - - /* NV12 surfaces contain a WxH sized luminance plane, followed by a - * (W/2)x(H/2) sized plane where each component is an UV pair. So the - * effective bitdepth is 12 bits per pixel. If the whole texture is - * interpreted as luminance data it looks approximately like this: - * - * +----------------------------------+---- - * | | - * | | - * | | - * | | - * | | 2 - * | LUMINANCE | - - * | | 3 - * | | - * | | - * | | - * | | - * +----------------------------------+---- - * |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV| - * |UVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUVUV| - * | | 1 - * | | - - * | | 3 - * | | - * | | - * +----------------------------------+---- */ - - /* First sample the chroma values. */ - shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); - /* We only have half the number of chroma pixels. */ - shader_addline(buffer, " texcoord.x *= 0.5;\n"); - shader_addline(buffer, " texcoord.y = (texcoord.y + 2.0) / 3.0;\n"); - - /* We must not allow filtering horizontally, this would mix U and V. - * Vertical filtering is ok. However, bear in mind that the pixel center - * is at 0.5, so add 0.5. */ - - /* Convert to non-normalised coordinates so we can find the individual - * pixel. */ - shader_addline(buffer, " texcoord.x = floor(texcoord.x * size.x);\n"); - /* Multiply by 2 since chroma components are stored in UV pixel pairs, add - * 0.5 to hit the center of the pixel. Then convert back to normalised - * coordinates. */ - shader_addline(buffer, " texcoord.x = (texcoord.x * 2.0 + 0.5) / size.x;\n"); - /* Clamp, keep the half pixel origin in mind. */ - shader_addline(buffer, " texcoord.y = max(texcoord.y, 2.0 / 3.0 + 0.5 / size.y);\n"); - - shader_addline(buffer, " chroma.y = texture%s(sampler, texcoord.xy).%c;\n", tex, component); - /* Add 1.0 / size.x to sample the adjacent texel. */ - shader_addline(buffer, " texcoord.x += 1.0 / size.x;\n"); - shader_addline(buffer, " chroma.x = texture%s(sampler, texcoord.xy).%c;\n", tex, component); - - /* Sample the luminance value. It is in the top 2/3rd of the texture, so - * scale the y coordinate. Clamp the y coordinate to prevent the chroma - * values from bleeding into the sampled luminance values due to - * filtering. */ - shader_addline(buffer, " texcoord.xy = out_texcoord.xy;\n"); - /* Multiply the y coordinate by 2/3 and clamp it. */ - shader_addline(buffer, " texcoord.y = min(texcoord.y * 2.0 / 3.0, 2.0 / 3.0 - 0.5 / size.y);\n"); - shader_addline(buffer, " luminance = texture%s(sampler, texcoord.xy).%c;\n", tex, component); -} - -static void glsl_blitter_generate_yuv_shader(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, - const char *output, const char *tex_type, const char *swizzle) -{ - enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); - - shader_addline(buffer, "const vec4 yuv_coef = vec4(1.403, -0.344, -0.714, 1.770);\n"); - shader_addline(buffer, "float luminance;\n"); - shader_addline(buffer, "vec2 texcoord;\n"); - shader_addline(buffer, "vec2 chroma;\n"); - shader_addline(buffer, "uniform vec2 size;\n"); - - shader_addline(buffer, "\nvoid main()\n{\n"); - - switch (complex_fixup) - { - case COMPLEX_FIXUP_UYVY: - case COMPLEX_FIXUP_YUY2: - gen_packed_yuv_read(buffer, gl_info, args, tex_type); - break; - - case COMPLEX_FIXUP_YV12: - gen_yv12_read(buffer, gl_info, tex_type); - break; - - case COMPLEX_FIXUP_NV12: - gen_nv12_read(buffer, gl_info, tex_type); - break; - - default: - FIXME("Unsupported fixup %#x.\n", complex_fixup); - string_buffer_free(buffer); - return; - } - - /* Calculate the final result. Formula is taken from - * http://www.fourcc.org/fccyvrgb.php. Note that the chroma - * ranges from -0.5 to 0.5. */ - shader_addline(buffer, "\n chroma.xy -= 0.5;\n"); - - shader_addline(buffer, " %s.x = luminance + chroma.x * yuv_coef.x;\n", output); - shader_addline(buffer, " %s.y = luminance + chroma.y * yuv_coef.y + chroma.x * yuv_coef.z;\n", output); - shader_addline(buffer, " %s.z = luminance + chroma.y * yuv_coef.w;\n", output); - - shader_addline(buffer, "}\n"); -} - -static void glsl_blitter_generate_plain_shader(struct wined3d_string_buffer *buffer, - const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args, - const char *output, const char *tex_type, const char *swizzle) -{ - shader_addline(buffer, "\nvoid main()\n{\n"); - shader_addline(buffer, " %s = texture%s(sampler, out_texcoord.%s);\n", - output, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle); - shader_glsl_color_correction_ext(buffer, output, WINED3DSP_WRITEMASK_ALL, args->fixup); - shader_addline(buffer, "}\n"); -} - -/* Context activation is done by the caller. */ -static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter, - const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args) -{ - static const struct - { - GLenum texture_target; - const char texture_type[7]; - const char texcoord_swizzle[4]; - } - texture_data[] = - { - {GL_TEXTURE_2D, "2D", "xy"}, - {GL_TEXTURE_CUBE_MAP, "Cube", "xyz"}, - {GL_TEXTURE_RECTANGLE_ARB, "2DRect", "xy"}, - }; - static const char vshader_main[] = - "\n" - "void main()\n" - "{\n" - " gl_Position = vec4(pos, 0.0, 1.0);\n" - " out_texcoord = texcoord;\n" - "}\n"; - enum complex_fixup complex_fixup = get_complex_fixup(args->fixup); - struct wined3d_string_buffer *buffer, *output; - GLuint program, vshader_id, fshader_id; - const char *tex_type, *swizzle, *ptr; - unsigned int i; - GLint loc; - - for (i = 0; i < ARRAY_SIZE(texture_data); ++i) - { - if (args->texture_type == texture_data[i].texture_target) - { - tex_type = texture_data[i].texture_type; - swizzle = texture_data[i].texcoord_swizzle; - break; - } - } - if (i == ARRAY_SIZE(texture_data)) - { - FIXME("Unsupported texture type %#x.\n", args->texture_type); - return 0; - } - - program = GL_EXTCALL(glCreateProgram()); - - vshader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); - - buffer = string_buffer_get(&blitter->string_buffers); - shader_glsl_add_version_declaration(buffer, gl_info); - shader_addline(buffer, "%s vec2 pos;\n", get_attribute_keyword(gl_info)); - shader_addline(buffer, "%s vec3 texcoord;\n", get_attribute_keyword(gl_info)); - declare_out_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n"); - shader_addline(buffer, vshader_main); - - ptr = buffer->buffer; - GL_EXTCALL(glShaderSource(vshader_id, 1, &ptr, NULL)); - GL_EXTCALL(glAttachShader(program, vshader_id)); - GL_EXTCALL(glDeleteShader(vshader_id)); - - fshader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); - - string_buffer_clear(buffer); - shader_glsl_add_version_declaration(buffer, gl_info); - shader_addline(buffer, "uniform sampler%s sampler;\n", tex_type); - declare_in_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n"); - if (!needs_legacy_glsl_syntax(gl_info)) - shader_addline(buffer, "out vec4 ps_out[1];\n"); - - output = string_buffer_get(&blitter->string_buffers); - string_buffer_sprintf(output, "%s[0]", get_fragment_output(gl_info)); - - switch (complex_fixup) - { - case COMPLEX_FIXUP_P8: - glsl_blitter_generate_p8_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); - break; - case COMPLEX_FIXUP_YUY2: - case COMPLEX_FIXUP_UYVY: - case COMPLEX_FIXUP_YV12: - case COMPLEX_FIXUP_NV12: - glsl_blitter_generate_yuv_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); - break; - case COMPLEX_FIXUP_NONE: - glsl_blitter_generate_plain_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle); - } - - string_buffer_release(&blitter->string_buffers, output); - - ptr = buffer->buffer; - GL_EXTCALL(glShaderSource(fshader_id, 1, &ptr, NULL)); - string_buffer_release(&blitter->string_buffers, buffer); - GL_EXTCALL(glAttachShader(program, fshader_id)); - GL_EXTCALL(glDeleteShader(fshader_id)); - - GL_EXTCALL(glBindAttribLocation(program, 0, "pos")); - GL_EXTCALL(glBindAttribLocation(program, 1, "texcoord")); - - if (!needs_legacy_glsl_syntax(gl_info)) - GL_EXTCALL(glBindFragDataLocation(program, 0, "ps_out")); - - GL_EXTCALL(glCompileShader(vshader_id)); - print_glsl_info_log(gl_info, vshader_id, FALSE); - GL_EXTCALL(glCompileShader(fshader_id)); - print_glsl_info_log(gl_info, fshader_id, FALSE); - GL_EXTCALL(glLinkProgram(program)); - shader_glsl_validate_link(gl_info, program); - - GL_EXTCALL(glUseProgram(program)); - loc = GL_EXTCALL(glGetUniformLocation(program, "sampler")); - GL_EXTCALL(glUniform1i(loc, 0)); - if (complex_fixup == COMPLEX_FIXUP_P8) - { - loc = GL_EXTCALL(glGetUniformLocation(program, "sampler_palette")); - GL_EXTCALL(glUniform1i(loc, 1)); - } - - return program; -} - -/* Context activation is done by the caller. */ -static void glsl_blitter_upload_palette(struct wined3d_glsl_blitter *blitter, - struct wined3d_context *context, const struct wined3d_texture *texture) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - const struct wined3d_palette *palette; - - palette = texture->swapchain ? texture->swapchain->palette : NULL; - - if (!blitter->palette_texture) - gl_info->gl_ops.gl.p_glGenTextures(1, &blitter->palette_texture); - - context_active_texture(context, gl_info, 1); - gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, blitter->palette_texture); - gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - if (palette) - { - gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_BGRA, - GL_UNSIGNED_INT_8_8_8_8_REV, palette->colors); - } - else - { - static const DWORD black; - - FIXME("P8 texture loaded without a palette.\n"); - gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 1, 0, GL_BGRA, - GL_UNSIGNED_INT_8_8_8_8_REV, &black); - } - - context_active_texture(context, gl_info, 0); -} - -/* Context activation is done by the caller. */ -static struct glsl_blitter_program *glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter, - struct wined3d_context *context, const struct wined3d_texture *texture) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - struct glsl_blitter_program *program; - struct glsl_blitter_args args; - struct wine_rb_entry *entry; - - memset(&args, 0, sizeof(args)); - args.texture_type = texture->target; - args.fixup = texture->resource.format->color_fixup; - - if ((entry = wine_rb_get(&blitter->programs, &args))) - return WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry); - - if (!(program = heap_alloc(sizeof(*program)))) - { - ERR("Failed to allocate blitter program memory.\n"); - return NULL; - } - - program->args = args; - if (!(program->id = glsl_blitter_generate_program(blitter, gl_info, &args))) - { - WARN("Failed to generate blitter program.\n"); - heap_free(program); - return NULL; - } - - if (wine_rb_put(&blitter->programs, &program->args, &program->entry) == -1) - { - ERR("Failed to store blitter program.\n"); - GL_EXTCALL(glDeleteProgram(program->id)); - heap_free(program); - return NULL; - } - - return program; -} - -static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context, - const struct wined3d_texture *src_texture, DWORD src_location, - const struct wined3d_texture *dst_texture, DWORD dst_location) -{ - const struct wined3d_resource *src_resource = &src_texture->resource; - const struct wined3d_resource *dst_resource = &dst_texture->resource; - const struct wined3d_format *src_format = src_resource->format; - const struct wined3d_format *dst_format = dst_resource->format; - BOOL decompress; - - if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id) - { - if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) - blit_op = WINED3D_BLIT_OP_DEPTH_BLIT; - else - blit_op = WINED3D_BLIT_OP_COLOR_BLIT; - } - - if (blit_op != WINED3D_BLIT_OP_COLOR_BLIT) - { - TRACE("Unsupported blit_op %#x.\n", blit_op); - return FALSE; - } - - if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) - return FALSE; - - if (src_texture->target == GL_TEXTURE_2D_MULTISAMPLE - || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE - || src_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY - || dst_texture->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) - { - TRACE("Multi-sample textures not supported.\n"); - return FALSE; - } - - /* We don't necessarily want to blit from resources without - * WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress - * compressed textures. */ - decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) - && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED); - if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) - { - TRACE("Source or destination resource does not have GPU access.\n"); - return FALSE; - } - - if (!is_identity_fixup(dst_format->color_fixup) - && (dst_format->id != src_format->id || dst_location != WINED3D_LOCATION_DRAWABLE)) - { - TRACE("Destination fixups are not supported.\n"); - return FALSE; - } - - TRACE("Returning supported.\n"); - return TRUE; -} - -static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, - unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) -{ - struct wined3d_device *device = dst_texture->resource.device; - const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_texture *staging_texture = NULL; - struct wined3d_glsl_blitter *glsl_blitter; - struct glsl_blitter_program *program; - struct wined3d_blitter *next; - unsigned int src_level; - GLint location; - RECT s, d; - - TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", - blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), - wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); - - if (!glsl_blitter_supported(op, context, src_texture, src_location, dst_texture, dst_location)) - { - if (!(next = blitter->next)) - { - ERR("No blitter to handle blit op %#x.\n", op); - return dst_location; - } - - TRACE("Forwarding to blitter %p.\n", next); - return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); - } - - glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); - - if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) - { - struct wined3d_resource_desc desc; - struct wined3d_box upload_box; - HRESULT hr; - - TRACE("Source texture is not GPU accessible, creating a staging texture.\n"); - - src_level = src_sub_resource_idx % src_texture->level_count; - desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; - desc.format = src_texture->resource.format->id; - desc.multisample_type = src_texture->resource.multisample_type; - desc.multisample_quality = src_texture->resource.multisample_quality; - desc.usage = WINED3DUSAGE_PRIVATE; - desc.access = WINED3D_RESOURCE_ACCESS_GPU; - desc.width = wined3d_texture_get_level_width(src_texture, src_level); - desc.height = wined3d_texture_get_level_height(src_texture, src_level); - desc.depth = 1; - desc.size = 0; - - if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0, - NULL, NULL, &wined3d_null_parent_ops, &staging_texture))) - { - ERR("Failed to create staging texture, hr %#x.\n", hr); - return dst_location; - } - - wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth); - wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0, - src_texture, src_sub_resource_idx, &upload_box); - - src_texture = staging_texture; - src_sub_resource_idx = 0; - } - else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO - && (src_texture->sub_resources[src_sub_resource_idx].locations - & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE - && !wined3d_resource_is_offscreen(&src_texture->resource)) - { - - /* Without FBO blits transferring from the drawable to the texture is - * expensive, because we have to flip the data in sysmem. Since we can - * flip in the blitter, we don't actually need that flip anyway. So we - * use the surface's texture as scratch texture, and flip the source - * rectangle instead. */ - texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context); - - s = *src_rect; - src_level = src_sub_resource_idx % src_texture->level_count; - s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top; - s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom; - src_rect = &s; - } - else - { - wined3d_texture_load(src_texture, context, FALSE); - } - - context_apply_blit_state(context, device); - - if (dst_location == WINED3D_LOCATION_DRAWABLE) - { - d = *dst_rect; - wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d); - dst_rect = &d; - } - - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) - { - GLenum buffer; - - if (dst_location == WINED3D_LOCATION_DRAWABLE) - { - TRACE("Destination texture %p is onscreen.\n", dst_texture); - buffer = wined3d_texture_get_gl_buffer(dst_texture); - } - else - { - TRACE("Destination texture %p is offscreen.\n", dst_texture); - buffer = GL_COLOR_ATTACHMENT0; - } - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, - &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location); - context_set_draw_buffer(context, buffer); - context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); - context_invalidate_state(context, STATE_FRAMEBUFFER); - } - - if (!(program = glsl_blitter_get_program(glsl_blitter, context, src_texture))) - { - ERR("Failed to get blitter program.\n"); - return dst_location; - } - GL_EXTCALL(glUseProgram(program->id)); - switch (get_complex_fixup(program->args.fixup)) - { - case COMPLEX_FIXUP_P8: - glsl_blitter_upload_palette(glsl_blitter, context, src_texture); - break; - - case COMPLEX_FIXUP_YUY2: - case COMPLEX_FIXUP_UYVY: - case COMPLEX_FIXUP_YV12: - case COMPLEX_FIXUP_NV12: - src_level = src_sub_resource_idx % src_texture->level_count; - location = GL_EXTCALL(glGetUniformLocation(program->id, "size")); - GL_EXTCALL(glUniform2f(location, wined3d_texture_get_level_pow2_width(src_texture, src_level), - wined3d_texture_get_level_pow2_height(src_texture, src_level))); - break; - - default: - break; - } - context_draw_shaded_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter); - GL_EXTCALL(glUseProgram(0)); - - if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture)) - gl_info->gl_ops.gl.p_glFlush(); - - if (staging_texture) - wined3d_texture_decref(staging_texture); - - return dst_location; -} - -static void glsl_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device, - unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, - const RECT *draw_rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) -{ - struct wined3d_blitter *next; - - if ((next = blitter->next)) - next->ops->blitter_clear(next, device, rt_count, fb, rect_count, - clear_rects, draw_rect, flags, color, depth, stencil); -} - -static const struct wined3d_blitter_ops glsl_blitter_ops = -{ - glsl_blitter_destroy, - glsl_blitter_clear, - glsl_blitter_blit, -}; - -struct wined3d_blitter *wined3d_glsl_blitter_create(struct wined3d_blitter **next, - const struct wined3d_device *device) -{ - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - struct wined3d_glsl_blitter *blitter; - - if (device->shader_backend != &glsl_shader_backend) - return NULL; - - if (!gl_info->supported[ARB_VERTEX_SHADER] || !gl_info->supported[ARB_FRAGMENT_SHADER]) - return NULL; - - if (!(blitter = heap_alloc(sizeof(*blitter)))) - { - ERR("Failed to allocate blitter.\n"); - return NULL; - } - - TRACE("Created blitter %p.\n", blitter); - - blitter->blitter.ops = &glsl_blitter_ops; - blitter->blitter.next = *next; - string_buffer_list_init(&blitter->string_buffers); - wine_rb_init(&blitter->programs, glsl_blitter_args_compare); - blitter->palette_texture = 0; - *next = &blitter->blitter; - - return *next; -} diff --git a/dll/directx/wine/wined3d/nvidia_texture_shader.c b/dll/directx/wine/wined3d/nvidia_texture_shader.c index 20db62739b5..0baa414e57d 100644 --- a/dll/directx/wine/wined3d/nvidia_texture_shader.c +++ b/dll/directx/wine/wined3d/nvidia_texture_shader.c @@ -69,9 +69,6 @@ static void nvts_activate_dimensions(const struct wined3d_state *state, DWORD st gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB); checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)"); break; - default: - FIXME("Unhandled target %#x.\n", state->textures[stage]->target); - break; } } else diff --git a/dll/directx/wine/wined3d/resource.c b/dll/directx/wine/wined3d/resource.c index df73997c84c..8b7f17bb6bd 100644 --- a/dll/directx/wine/wined3d/resource.c +++ b/dll/directx/wine/wined3d/resource.c @@ -95,9 +95,6 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * return WINED3DERR_INVALIDCALL; } - if (!size) - ERR("Attempting to create a zero-sized resource.\n"); - for (i = 0; i < ARRAY_SIZE(resource_types); ++i) { if (resource_types[i].type != type @@ -194,7 +191,19 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * resource->parent_ops = parent_ops; resource->resource_ops = resource_ops; resource->map_binding = WINED3D_LOCATION_SYSMEM; - resource->heap_memory = NULL; + + if (size) + { + if (!wined3d_resource_allocate_sysmem(resource)) + { + ERR("Failed to allocate system memory.\n"); + return E_OUTOFMEMORY; + } + } + else + { + resource->heap_memory = NULL; + } if (!(usage & WINED3DUSAGE_PRIVATE)) { @@ -203,7 +212,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * { if (size > wined3d_device_get_available_texture_mem(device)) { - ERR("Out of adapter memory.\n"); + ERR("Out of adapter memory\n"); + wined3d_resource_free_sysmem(resource); return WINED3DERR_OUTOFVIDEOMEMORY; } adapter_adjust_memory(device->adapter, size); @@ -220,7 +230,7 @@ static void wined3d_resource_destroy_object(void *object) struct wined3d_resource *resource = object; wined3d_resource_free_sysmem(resource); - context_resource_released(resource->device, resource); + context_resource_released(resource->device, resource, resource->type); wined3d_resource_release(resource); } @@ -481,10 +491,7 @@ BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) void *mem; if (!(mem = heap_alloc_zero(resource->size + align))) - { - ERR("Failed to allocate system memory.\n"); return FALSE; - } p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1; *p = mem; diff --git a/dll/directx/wine/wined3d/shader.c b/dll/directx/wine/wined3d/shader.c index 9075fc7ebc6..0513c9e2053 100644 --- a/dll/directx/wine/wined3d/shader.c +++ b/dll/directx/wine/wined3d/shader.c @@ -419,15 +419,6 @@ static const struct wined3d_shader_frontend *shader_select_frontend(enum wined3d } } -static enum wined3d_shader_type shader_get_shader_type(const struct wined3d_shader_desc *desc) -{ - if (desc->format == WINED3D_SHADER_BYTE_CODE_FORMAT_SM4) - return wined3d_get_sm4_shader_type(desc->byte_code, desc->byte_code_size); - - FIXME("Could not get shader type for byte code format %#x.\n", desc->format); - return WINED3D_SHADER_TYPE_INVALID; -} - void string_buffer_clear(struct wined3d_string_buffer *buffer) { buffer->buffer[0] = '\0'; @@ -810,10 +801,6 @@ static BOOL shader_record_register_usage(struct wined3d_shader *shader, struct w reg_maps->vocp = 1; break; - case WINED3DSPR_SAMPLEMASK: - reg_maps->sample_mask = 1; - break; - default: TRACE("Not recording register of type %#x and [%#x][%#x].\n", reg->type, reg->idx[0].offset, reg->idx[1].offset); @@ -996,49 +983,13 @@ static void wined3d_insert_interpolation_mode(DWORD *packed_interpolation_mode, register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT, mode); } -static HRESULT shader_scan_output_signature(struct wined3d_shader *shader) -{ - const struct wined3d_shader_signature *output_signature = &shader->output_signature; - struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; - unsigned int i; - HRESULT hr; - - for (i = 0; i < output_signature->element_count; ++i) - { - const struct wined3d_shader_signature_element *e = &output_signature->elements[i]; - unsigned int mask; - - reg_maps->output_registers |= 1u << e->register_idx; - if (e->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) - { - if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask))) - return hr; - reg_maps->clip_distance_mask |= mask; - } - else if (e->sysval_semantic == WINED3D_SV_CULL_DISTANCE) - { - if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask))) - return hr; - reg_maps->cull_distance_mask |= mask; - } - else if (e->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX) - { - reg_maps->viewport_array = 1; - } - } - - return WINED3D_OK; -} - /* Note that this does not count the loop register as an address register. */ -static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD constf_size) +static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe, + struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature *input_signature, + struct wined3d_shader_signature *output_signature, DWORD constf_size) { struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)]; struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT]; - struct wined3d_shader_signature *output_signature = &shader->output_signature; - struct wined3d_shader_signature *input_signature = &shader->input_signature; - struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; - const struct wined3d_shader_frontend *fe = shader->frontend; unsigned int cur_loop_depth = 0, max_loop_depth = 0; struct wined3d_shader_version shader_version; struct wined3d_shader_phase *phase = NULL; @@ -1716,8 +1667,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD co shader_record_sample(reg_maps, ins.src[2].reg.idx[0].offset, ins.src[3].reg.idx[0].offset, reg_maps->sampler_map.count); } - else if ((ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE) - || (ins.handler_idx == WINED3DSIH_SAMPLE_INFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE)) + else if (ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE) { shader_record_sample(reg_maps, ins.src[0].reg.idx[0].offset, WINED3D_SAMPLER_DEFAULT, reg_maps->sampler_map.count); @@ -1830,8 +1780,25 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD co if (output_signature->elements) { - if (FAILED(hr = shader_scan_output_signature(shader))) - return hr; + for (i = 0; i < output_signature->element_count; ++i) + { + const struct wined3d_shader_signature_element *e = &output_signature->elements[i]; + unsigned int mask; + + reg_maps->output_registers |= 1u << e->register_idx; + if (e->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) + { + if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask))) + return hr; + reg_maps->clip_distance_mask |= mask; + } + else if (e->sysval_semantic == WINED3D_SV_CULL_DISTANCE) + { + if (FAILED(hr = shader_calculate_clip_or_cull_distance_mask(e, &mask))) + return hr; + reg_maps->cull_distance_mask |= mask; + } + } } else if (reg_maps->output_registers) { @@ -1922,23 +1889,6 @@ static void shader_dump_sync_flags(struct wined3d_string_buffer *buffer, DWORD s shader_addline(buffer, "_unknown_flags(%#x)", sync_flags); } -static void shader_dump_precise_flags(struct wined3d_string_buffer *buffer, DWORD flags) -{ - if (!(flags & WINED3DSI_PRECISE_XYZW)) - return; - - shader_addline(buffer, " [precise"); - if (flags != WINED3DSI_PRECISE_XYZW) - { - shader_addline(buffer, "(%s%s%s%s)", - flags & WINED3DSI_PRECISE_X ? "x" : "", - flags & WINED3DSI_PRECISE_Y ? "y" : "", - flags & WINED3DSI_PRECISE_Z ? "z" : "", - flags & WINED3DSI_PRECISE_W ? "w" : ""); - } - shader_addline(buffer, "]"); -} - static void shader_dump_uav_flags(struct wined3d_string_buffer *buffer, DWORD uav_flags) { if (uav_flags & WINED3DSUF_GLOBALLY_COHERENT) @@ -2341,10 +2291,6 @@ static void shader_dump_register(struct wined3d_string_buffer *buffer, shader_addline(buffer, "null"); break; - case WINED3DSPR_RASTERIZER: - shader_addline(buffer, "rasterizer"); - break; - case WINED3DSPR_RESOURCE: shader_addline(buffer, "t"); break; @@ -3106,10 +3052,6 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe { shader_dump_sync_flags(&buffer, ins.flags); } - else - { - shader_dump_precise_flags(&buffer, ins.flags); - } if (wined3d_shader_instruction_has_texel_offset(&ins)) shader_addline(&buffer, "(%d,%d,%d)", ins.texel_offset.u, ins.texel_offset.v, ins.texel_offset.w); @@ -3324,11 +3266,11 @@ const struct wined3d_shader_backend_ops none_shader_backend = static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_const_count, enum wined3d_shader_type type, unsigned int max_version) { - const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info; struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; const struct wined3d_shader_frontend *fe; - unsigned int backend_version; HRESULT hr; + unsigned int backend_version; + const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info; TRACE("shader %p, float_const_count %u, type %#x, max_version %u.\n", shader, float_const_count, type, max_version); @@ -3346,7 +3288,8 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_co shader_trace_init(fe, shader->frontend_data); /* Second pass: figure out which registers are used, what the semantics are, etc. */ - if (FAILED(hr = shader_get_registers_used(shader, float_const_count))) + if (FAILED(hr = shader_get_registers_used(shader, fe, reg_maps, &shader->input_signature, + &shader->output_signature, float_const_count))) return hr; if (reg_maps->shader_version.type != type) @@ -3648,6 +3591,9 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device TRACE("byte_code %p, byte_code_size %#lx, format %#x, max_version %#x.\n", desc->byte_code, (long)desc->byte_code_size, desc->format, desc->max_version); + if (!desc->byte_code) + return WINED3DERR_INVALIDCALL; + if (!(shader->frontend = shader_select_frontend(desc->format))) { FIXME("Unable to find frontend for shader.\n"); @@ -3722,39 +3668,25 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr); } - if (desc->byte_code && byte_code_size) + if (!(shader->function = heap_alloc(byte_code_size))) { - if (!(shader->function = heap_alloc(byte_code_size))) - { - shader_cleanup(shader); - return E_OUTOFMEMORY; - } - memcpy(shader->function, desc->byte_code, byte_code_size); - shader->functionLength = byte_code_size; - - if (FAILED(hr = shader_set_function(shader, float_const_count, type, desc->max_version))) - { - WARN("Failed to set function, hr %#x.\n", hr); - shader_cleanup(shader); - return hr; - } + shader_cleanup(shader); + return E_OUTOFMEMORY; } - else - { - shader->reg_maps.shader_version.type = type; - shader->reg_maps.shader_version.major = 4; - shader->reg_maps.shader_version.minor = 0; - shader_set_limits(shader); + memcpy(shader->function, desc->byte_code, byte_code_size); + shader->functionLength = byte_code_size; - if (FAILED(hr = shader_scan_output_signature(shader))) - { - shader_cleanup(shader); - return hr; - } + if (FAILED(hr = shader_set_function(shader, float_const_count, type, desc->max_version))) + { + WARN("Failed to set function, hr %#x.\n", hr); + shader_cleanup(shader); + return hr; } shader->load_local_constsF = shader->lconst_inf_or_nan; + wined3d_cs_init_object(shader->device->cs, wined3d_shader_init_object, shader); + return hr; } @@ -3791,40 +3723,20 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3 const struct wined3d_shader_desc *desc, const struct wined3d_stream_output_desc *so_desc, void *parent, const struct wined3d_parent_ops *parent_ops) { - struct wined3d_shader_desc shader_desc = *desc; - struct wined3d_stream_output_element *elements; - enum wined3d_shader_type shader_type; + struct wined3d_stream_output_element *elements = NULL; HRESULT hr; - if (so_desc) - { - shader_type = shader_get_shader_type(desc); - switch (shader_type) - { - case WINED3D_SHADER_TYPE_VERTEX: - shader_desc.byte_code = NULL; - shader_desc.byte_code_size = 0; - break; - case WINED3D_SHADER_TYPE_DOMAIN: - FIXME("Stream output not supported for %s.\n", debug_shader_type(shader_type)); - return E_NOTIMPL; - default: - break; - } - } + if (so_desc && !(elements = heap_calloc(so_desc->element_count, sizeof(*elements)))) + return E_OUTOFMEMORY; - if (FAILED(hr = shader_init(shader, device, &shader_desc, 0, - WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops))) + if (FAILED(hr = shader_init(shader, device, desc, 0, WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops))) + { + heap_free(elements); return hr; + } if (so_desc) { - if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements)))) - { - shader_cleanup(shader); - return E_OUTOFMEMORY; - } - shader->u.gs.so_desc = *so_desc; shader->u.gs.so_desc.elements = elements; memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements)); @@ -3864,9 +3776,6 @@ void find_gs_compile_args(const struct wined3d_state *state, const struct wined3 args->output_count = pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output; - if (!(args->primitive_type = shader->u.gs.input_type)) - args->primitive_type = d3d_primitive_type_from_gl(state->gl_primitive_type); - init_interpolation_compile_args(args->interpolation_mode, pixel_shader, gl_info); } @@ -3964,7 +3873,8 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 switch (texture->target) { /* RECT textures are distinguished from 2D textures via np2_fixup */ - default: + case GL_TEXTURE_RECTANGLE_ARB: + case GL_TEXTURE_2D: break; case GL_TEXTURE_3D: @@ -4016,16 +3926,16 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 if (shader->reg_maps.shader_version.major >= 3) { if (position_transformed) - args->vp_mode = WINED3D_VP_MODE_NONE; + args->vp_mode = pretransformed; else if (use_vs(state)) - args->vp_mode = WINED3D_VP_MODE_SHADER; + args->vp_mode = vertexshader; else - args->vp_mode = WINED3D_VP_MODE_FF; + args->vp_mode = fixedfunction; args->fog = WINED3D_FFP_PS_FOG_OFF; } else { - args->vp_mode = WINED3D_VP_MODE_SHADER; + args->vp_mode = vertexshader; if (state->render_states[WINED3D_RS_FOGENABLE]) { switch (state->render_states[WINED3D_RS_FOGTABLEMODE]) @@ -4200,9 +4110,6 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4213,8 +4120,6 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created compute shader %p.\n", object); *shader = object; @@ -4230,9 +4135,6 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4243,8 +4145,6 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created domain shader %p.\n", object); *shader = object; @@ -4261,9 +4161,6 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const stru TRACE("device %p, desc %p, so_desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, so_desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4274,8 +4171,6 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created geometry shader %p.\n", object); *shader = object; @@ -4291,9 +4186,6 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4304,8 +4196,6 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created hull shader %p.\n", object); *shader = object; @@ -4321,9 +4211,6 @@ HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const stru TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4334,8 +4221,6 @@ HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created pixel shader %p.\n", object); *shader = object; @@ -4351,9 +4236,6 @@ HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const stru TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", device, desc, parent, parent_ops, shader); - if (!desc->byte_code) - return WINED3DERR_INVALIDCALL; - if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; @@ -4364,8 +4246,6 @@ HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const stru return hr; } - wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object); - TRACE("Created vertex shader %p.\n", object); *shader = object; diff --git a/dll/directx/wine/wined3d/shader_sm4.c b/dll/directx/wine/wined3d/shader_sm4.c index b119e8feaa8..8eac746ac50 100644 --- a/dll/directx/wine/wined3d/shader_sm4.c +++ b/dll/directx/wine/wined3d/shader_sm4.c @@ -61,9 +61,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode); #define WINED3D_SM4_GLOBAL_FLAGS_SHIFT 11 #define WINED3D_SM4_GLOBAL_FLAGS_MASK (0xffu << WINED3D_SM4_GLOBAL_FLAGS_SHIFT) -#define WINED3D_SM5_PRECISE_SHIFT 19 -#define WINED3D_SM5_PRECISE_MASK (0xfu << WINED3D_SM5_PRECISE_SHIFT) - #define WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT 11 #define WINED3D_SM5_CONTROL_POINT_COUNT_MASK (0xffu << WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT) @@ -318,7 +315,6 @@ enum wined3d_sm4_register_type WINED3D_SM4_RT_PRIMID = 0x0b, WINED3D_SM4_RT_DEPTHOUT = 0x0c, WINED3D_SM4_RT_NULL = 0x0d, - WINED3D_SM4_RT_RASTERIZER = 0x0e, WINED3D_SM4_RT_OMASK = 0x0f, WINED3D_SM5_RT_STREAM = 0x10, WINED3D_SM5_RT_FUNCTION_BODY = 0x11, @@ -1133,7 +1129,7 @@ static const enum wined3d_shader_register_type register_type_table[] = /* WINED3D_SM4_RT_PRIMID */ WINED3DSPR_PRIMID, /* WINED3D_SM4_RT_DEPTHOUT */ WINED3DSPR_DEPTHOUT, /* WINED3D_SM4_RT_NULL */ WINED3DSPR_NULL, - /* WINED3D_SM4_RT_RASTERIZER */ WINED3DSPR_RASTERIZER, + /* UNKNOWN */ ~0u, /* WINED3D_SM4_RT_OMASK */ WINED3DSPR_SAMPLEMASK, /* WINED3D_SM5_RT_STREAM */ WINED3DSPR_STREAM, /* WINED3D_SM5_RT_FUNCTION_BODY */ WINED3DSPR_FUNCTIONBODY, @@ -1222,43 +1218,6 @@ static enum wined3d_data_type map_data_type(char t) } } -enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code, size_t byte_code_size) -{ - DWORD shader_type; - - if (byte_code_size / sizeof(*byte_code) < 1) - { - WARN("Invalid byte code size %lu.\n", (long)byte_code_size); - return WINED3D_SHADER_TYPE_INVALID; - } - - shader_type = byte_code[0] >> 16; - switch (shader_type) - { - case WINED3D_SM4_PS: - return WINED3D_SHADER_TYPE_PIXEL; - break; - case WINED3D_SM4_VS: - return WINED3D_SHADER_TYPE_VERTEX; - break; - case WINED3D_SM4_GS: - return WINED3D_SHADER_TYPE_GEOMETRY; - break; - case WINED3D_SM5_HS: - return WINED3D_SHADER_TYPE_HULL; - break; - case WINED3D_SM5_DS: - return WINED3D_SHADER_TYPE_DOMAIN; - break; - case WINED3D_SM5_CS: - return WINED3D_SHADER_TYPE_COMPUTE; - break; - default: - FIXME("Unrecognised shader type %#x.\n", shader_type); - return WINED3D_SHADER_TYPE_INVALID; - } -} - static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size, const struct wined3d_shader_signature *output_signature) { @@ -1292,13 +1251,35 @@ static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size, priv->start = &byte_code[2]; priv->end = &byte_code[token_count]; - priv->shader_version.type = wined3d_get_sm4_shader_type(byte_code, byte_code_size); - if (priv->shader_version.type == WINED3D_SHADER_TYPE_INVALID) + switch (version_token >> 16) { - heap_free(priv); - return NULL; - } + case WINED3D_SM4_PS: + priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL; + break; + + case WINED3D_SM4_VS: + priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX; + break; + + case WINED3D_SM4_GS: + priv->shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY; + break; + case WINED3D_SM5_HS: + priv->shader_version.type = WINED3D_SHADER_TYPE_HULL; + break; + + case WINED3D_SM5_DS: + priv->shader_version.type = WINED3D_SHADER_TYPE_DOMAIN; + break; + + case WINED3D_SM5_CS: + priv->shader_version.type = WINED3D_SHADER_TYPE_COMPUTE; + break; + + default: + FIXME("Unrecognised shader type %#x.\n", version_token >> 16); + } priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token); priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token); @@ -1647,7 +1628,6 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi unsigned int i, len; SIZE_T remaining; const DWORD *p; - DWORD precise; list_move_head(&priv->src_free, &priv->src); @@ -1722,13 +1702,12 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi shader_sm4_read_instruction_modifier(previous_token = *p++, ins); ins->flags = (opcode_token & WINED3D_SM4_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT; + if (ins->flags & WINED3D_SM4_INSTRUCTION_FLAG_SATURATE) { ins->flags &= ~WINED3D_SM4_INSTRUCTION_FLAG_SATURATE; instruction_dst_modifier = WINED3DSPDM_SATURATE; } - precise = (opcode_token & WINED3D_SM5_PRECISE_MASK) >> WINED3D_SM5_PRECISE_SHIFT; - ins->flags |= precise << WINED3DSI_PRECISE_SHIFT; for (i = 0; i < ins->dst_count; ++i) { diff --git a/dll/directx/wine/wined3d/state.c b/dll/directx/wine/wined3d/state.c index 1bd38632b82..2f506c36d16 100644 --- a/dll/directx/wine/wined3d/state.c +++ b/dll/directx/wine/wined3d/state.c @@ -36,6 +36,7 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); ULONG CDECL wined3d_blend_state_incref(struct wined3d_blend_state *state) { @@ -1013,7 +1014,7 @@ static void state_stencil(struct wined3d_context *context, const struct wined3d_ } } -static void state_stencilwrite2s_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; const struct wined3d_gl_info *gl_info = context->gl_info; @@ -1830,6 +1831,28 @@ static void state_depthbias(struct wined3d_context *context, const struct wined3 checkGLcall("depth bias"); } +static void state_depthclip(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (state->render_states[WINED3D_RS_DEPTHCLIP]) + { + gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP); + checkGLcall("glDisable(GL_DEPTH_CLAMP)"); + } + else + { + gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP); + checkGLcall("glEnable(GL_DEPTH_CLAMP)"); + } +} + +static void state_depthclip_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +{ + if (!state->render_states[WINED3D_RS_DEPTHCLIP]) + FIXME("Depth clamping not supported by GL.\n"); +} + static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { if (state->render_states[WINED3D_RS_ZVISIBLE]) @@ -3311,6 +3334,76 @@ static void transform_texture(struct wined3d_context *context, const struct wine checkGLcall("glLoadMatrixf"); } +static void unload_tex_coords(const struct wined3d_gl_info *gl_info) +{ + unsigned int texture_idx; + + for (texture_idx = 0; texture_idx < gl_info->limits.texture_coords; ++texture_idx) + { + GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx)); + gl_info->gl_ops.gl.p_glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +static void load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si, + GLuint *curVBO, const struct wined3d_state *state) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int mapped_stage = 0; + unsigned int textureNo; + + for (textureNo = 0; textureNo < context->d3d_info->limits.ffp_blend_stages; ++textureNo) + { + int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX]; + + mapped_stage = context->tex_unit_map[textureNo]; + if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue; + + if (mapped_stage >= gl_info->limits.texture_coords) + { + FIXME("Attempted to load unsupported texture coordinate %u\n", mapped_stage); + continue; + } + + if (coordIdx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coordIdx)))) + { + const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; + + TRACE("Setting up texture %u, idx %d, coordindx %u, data {%#x:%p}.\n", + textureNo, mapped_stage, coordIdx, e->data.buffer_object, e->data.addr); + + if (*curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + *curVBO = e->data.buffer_object; + } + + GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glClientActiveTextureARB"); + + /* The coords to supply depend completely on the fvf / vertex shader */ + gl_info->gl_ops.gl.p_glTexCoordPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1)); + } + } + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */ + for (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo) + { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1)); + } + } + + checkGLcall("loadTexCoords"); +} + static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); @@ -3481,8 +3574,8 @@ static void tex_coordindex(struct wined3d_context *context, const struct wined3d */ GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; - context_unload_tex_coords(context); - context_load_tex_coords(context, &context->stream_info, &curVBO, state); + unload_tex_coords(gl_info); + load_tex_coords(context, &context->stream_info, &curVBO, state); } } @@ -3772,9 +3865,41 @@ void clipplane(struct wined3d_context *context, const struct wined3d_state *stat static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - unsigned int matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)); + UINT matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)); + const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum glMat; + + TRACE("Setting world matrix %d\n", matrix); + + if (matrix >= gl_info->limits.blends) + { + WARN("Unsupported blend matrix set\n"); + return; + } + + if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW))) + return; + + /* GL_MODELVIEW0_ARB: 0x1700 + * GL_MODELVIEW1_ARB: 0x850a + * GL_MODELVIEW2_ARB: 0x8722 + * GL_MODELVIEW3_ARB: 0x8723 + * etc + * GL_MODELVIEW31_ARB: 0x873f + */ + if(matrix == 1) glMat = GL_MODELVIEW1_ARB; + else glMat = GL_MODELVIEW2_ARB - 2 + matrix; + + gl_info->gl_ops.gl.p_glMatrixMode(glMat); + checkGLcall("glMatrixMode(glMat)"); - WARN("Unsupported world matrix %u set.\n", matrix); + /* World matrix 0 is multiplied with the view matrix because d3d uses 3 + * matrices while gl uses only 2. To avoid weighting the view matrix + * incorrectly it has to be multiplied into every GL modelview matrix. */ + gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11); + checkGLcall("glLoadMatrixf"); + gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)]._11); + checkGLcall("glMultMatrixf"); } static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -3789,6 +3914,50 @@ static void state_vertexblend_w(struct wined3d_context *context, const struct wi else WARN("Vertex blend flags %#x not supported.\n", f); } +static void state_vertexblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +{ + enum wined3d_vertex_blend_flags val = state->render_states[WINED3D_RS_VERTEXBLEND]; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_device *device = context->device; + static unsigned int once; + + switch (val) + { + case WINED3D_VBF_1WEIGHTS: + case WINED3D_VBF_2WEIGHTS: + case WINED3D_VBF_3WEIGHTS: + gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_BLEND_ARB); + checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)"); + + /* D3D adds one more matrix which has weight (1 - sum(weights)). + * This is enabled at context creation with enabling + * GL_WEIGHT_SUM_UNITY_ARB. */ + GL_EXTCALL(glVertexBlendARB(state->render_states[WINED3D_RS_VERTEXBLEND] + 1)); + + if (!device->vertexBlendUsed) + { + unsigned int i; + for (i = 1; i < gl_info->limits.blends; ++i) + { + if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i)))) + transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i))); + } + device->vertexBlendUsed = TRUE; + } + break; + + case WINED3D_VBF_TWEENING: + case WINED3D_VBF_0WEIGHTS: /* Indexed vertex blending, not supported. */ + if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val); + else WARN("Vertex blend flags %#x not supported.\n", val); + /* Fall through. */ + case WINED3D_VBF_DISABLE: + gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_BLEND_ARB); + checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)"); + break; + } +} + static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -3839,6 +4008,16 @@ static void transform_view(struct wined3d_context *context, const struct wined3d * No need to do it here if the state is scheduled for update. */ if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)))) transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))); + + /* Avoid looping over a number of matrices if the app never used the functionality */ + if (context->device->vertexBlendUsed) + { + for (k = 1; k < gl_info->limits.blends; ++k) + { + if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k)))) + transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k))); + } + } } static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -3854,18 +4033,518 @@ static void transform_projection(struct wined3d_context *context, const struct w checkGLcall("glLoadMatrixf"); } +/* This should match any arrays loaded in load_vertex_data. + * TODO: Only load / unload arrays if we have to. */ +static void unload_vertex_data(const struct wined3d_gl_info *gl_info) +{ + gl_info->gl_ops.gl.p_glDisableClientState(GL_VERTEX_ARRAY); + gl_info->gl_ops.gl.p_glDisableClientState(GL_NORMAL_ARRAY); + gl_info->gl_ops.gl.p_glDisableClientState(GL_COLOR_ARRAY); + if (gl_info->supported[EXT_SECONDARY_COLOR]) + gl_info->gl_ops.gl.p_glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + if (gl_info->supported[ARB_VERTEX_BLEND]) + gl_info->gl_ops.gl.p_glDisableClientState(GL_WEIGHT_ARRAY_ARB); + unload_tex_coords(gl_info); +} + +static inline void unload_numbered_array(struct wined3d_context *context, int i) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + GL_EXTCALL(glDisableVertexAttribArray(i)); + checkGLcall("glDisableVertexAttribArray"); + if (gl_info->supported[ARB_INSTANCED_ARRAYS]) + GL_EXTCALL(glVertexAttribDivisor(i, 0)); + + context->numbered_array_mask &= ~(1u << i); +} + +/* This should match any arrays loaded in loadNumberedArrays + * TODO: Only load / unload arrays if we have to. */ +static void unload_numbered_arrays(struct wined3d_context *context) +{ + /* disable any attribs (this is the same for both GLSL and ARB modes) */ + int i; + + for (i = 0; i < context->gl_info->limits.vertex_attribs; ++i) { + unload_numbered_array(context, i); + } +} + +static void load_numbered_arrays(struct wined3d_context *context, + const struct wined3d_stream_info *stream_info, const struct wined3d_state *state) +{ + const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; + unsigned int i; + + /* Default to no instancing */ + context->instance_count = 0; + + for (i = 0; i < MAX_ATTRIBS; ++i) + { + const struct wined3d_stream_info_element *element = &stream_info->elements[i]; + const struct wined3d_stream_state *stream; + + if (!(stream_info->use_map & (1u << i))) + { + if (context->numbered_array_mask & (1u << i)) + unload_numbered_array(context, i); + if (!use_vs(state) && i == WINED3D_FFP_DIFFUSE) + GL_EXTCALL(glVertexAttrib4f(i, 1.0f, 1.0f, 1.0f, 1.0f)); + else + GL_EXTCALL(glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f)); + continue; + } + + stream = &state->streams[element->stream_idx]; + + if ((stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) && !context->instance_count) + context->instance_count = state->streams[0].frequency ? state->streams[0].frequency : 1; + + if (gl_info->supported[ARB_INSTANCED_ARRAYS]) + { + GL_EXTCALL(glVertexAttribDivisor(i, element->divisor)); + } + else if (element->divisor) + { + /* Unload instanced arrays, they will be loaded using + * immediate mode instead. */ + if (context->numbered_array_mask & (1u << i)) + unload_numbered_array(context, i); + continue; + } + + TRACE_(d3d_shader)("Loading array %u [VBO=%u].\n", i, element->data.buffer_object); + + if (element->stride) + { + if (curVBO != element->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, element->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = element->data.buffer_object; + } + /* Use the VBO to find out if a vertex buffer exists, not the vb + * pointer. vb can point to a user pointer data blob. In that case + * curVBO will be 0. If there is a vertex buffer but no vbo we + * won't be load converted attributes anyway. */ + if (vs && vs->reg_maps.shader_version.major >= 4 + && (element->format->flags[WINED3D_GL_RES_TYPE_BUFFER] & WINED3DFMT_FLAG_INTEGER)) + { + GL_EXTCALL(glVertexAttribIPointer(i, element->format->gl_vtx_format, element->format->gl_vtx_type, + element->stride, element->data.addr + state->load_base_vertex_index * element->stride)); + } + else + { + GL_EXTCALL(glVertexAttribPointer(i, element->format->gl_vtx_format, element->format->gl_vtx_type, + element->format->gl_normalized, element->stride, + element->data.addr + state->load_base_vertex_index * element->stride)); + } + + if (!(context->numbered_array_mask & (1u << i))) + { + GL_EXTCALL(glEnableVertexAttribArray(i)); + context->numbered_array_mask |= (1u << i); + } + } + else + { + /* Stride = 0 means always the same values. + * glVertexAttribPointer doesn't do that. Instead disable the + * pointer and set up the attribute statically. But we have to + * figure out the system memory address. */ + const BYTE *ptr = element->data.addr; + if (element->data.buffer_object) + ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(stream->buffer, context); + + if (context->numbered_array_mask & (1u << i)) + unload_numbered_array(context, i); + + switch (element->format->id) + { + case WINED3DFMT_R32_FLOAT: + GL_EXTCALL(glVertexAttrib1fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32_FLOAT: + GL_EXTCALL(glVertexAttrib2fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32_FLOAT: + GL_EXTCALL(glVertexAttrib3fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32A32_FLOAT: + GL_EXTCALL(glVertexAttrib4fv(i, (const GLfloat *)ptr)); + break; + + case WINED3DFMT_R8G8B8A8_UINT: + GL_EXTCALL(glVertexAttrib4ubv(i, ptr)); + break; + case WINED3DFMT_B8G8R8A8_UNORM: + if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA]) + { + const DWORD *src = (const DWORD *)ptr; + DWORD c = *src & 0xff00ff00u; + c |= (*src & 0xff0000u) >> 16; + c |= (*src & 0xffu) << 16; + GL_EXTCALL(glVertexAttrib4Nubv(i, (GLubyte *)&c)); + break; + } + /* else fallthrough */ + case WINED3DFMT_R8G8B8A8_UNORM: + GL_EXTCALL(glVertexAttrib4Nubv(i, ptr)); + break; + + case WINED3DFMT_R16G16_SINT: + GL_EXTCALL(glVertexAttrib2sv(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_SINT: + GL_EXTCALL(glVertexAttrib4sv(i, (const GLshort *)ptr)); + break; + + case WINED3DFMT_R16G16_SNORM: + { + const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4Nsv(i, s)); + break; + } + case WINED3DFMT_R16G16_UNORM: + { + const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4Nusv(i, s)); + break; + } + case WINED3DFMT_R16G16B16A16_SNORM: + GL_EXTCALL(glVertexAttrib4Nsv(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_UNORM: + GL_EXTCALL(glVertexAttrib4Nusv(i, (const GLushort *)ptr)); + break; + + case WINED3DFMT_R10G10B10X2_UINT: + FIXME("Unsure about WINED3DDECLTYPE_UDEC3.\n"); + /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */ + break; + case WINED3DFMT_R10G10B10X2_SNORM: + FIXME("Unsure about WINED3DDECLTYPE_DEC3N.\n"); + /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */ + break; + + case WINED3DFMT_R16G16_FLOAT: + if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM]) + { + /* Not supported by GL_ARB_half_float_vertex. */ + GL_EXTCALL(glVertexAttrib2hvNV(i, (const GLhalfNV *)ptr)); + } + else + { + float x = float_16_to_32(((const unsigned short *)ptr) + 0); + float y = float_16_to_32(((const unsigned short *)ptr) + 1); + GL_EXTCALL(glVertexAttrib2f(i, x, y)); + } + break; + case WINED3DFMT_R16G16B16A16_FLOAT: + if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM]) + { + /* Not supported by GL_ARB_half_float_vertex. */ + GL_EXTCALL(glVertexAttrib4hvNV(i, (const GLhalfNV *)ptr)); + } + else + { + float x = float_16_to_32(((const unsigned short *)ptr) + 0); + float y = float_16_to_32(((const unsigned short *)ptr) + 1); + float z = float_16_to_32(((const unsigned short *)ptr) + 2); + float w = float_16_to_32(((const unsigned short *)ptr) + 3); + GL_EXTCALL(glVertexAttrib4f(i, x, y, z, w)); + } + break; + + default: + ERR("Unexpected declaration in stride 0 attributes.\n"); + break; + + } + } + } + checkGLcall("Loading numbered arrays"); +} + +static void load_vertex_data(struct wined3d_context *context, + const struct wined3d_stream_info *si, const struct wined3d_state *state) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; + const struct wined3d_stream_info_element *e; + + TRACE("Using fast vertex array code\n"); + + /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */ + context->instance_count = 0; + + /* Blend Data ---------------------------------------------- */ + if ((si->use_map & (1u << WINED3D_FFP_BLENDWEIGHT)) + || si->use_map & (1u << WINED3D_FFP_BLENDINDICES)) + { + e = &si->elements[WINED3D_FFP_BLENDWEIGHT]; + + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + TRACE("Blend %u %p %u\n", e->format->component_count, + e->data.addr + state->load_base_vertex_index * e->stride, e->stride); + + gl_info->gl_ops.gl.p_glEnableClientState(GL_WEIGHT_ARRAY_ARB); + checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)"); + + GL_EXTCALL(glVertexBlendARB(e->format->component_count + 1)); + + if (curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = e->data.buffer_object; + } + + TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n", + e->format->gl_vtx_format, + e->format->gl_vtx_type, + e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glWeightPointerARB(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + + checkGLcall("glWeightPointerARB"); + + if (si->use_map & (1u << WINED3D_FFP_BLENDINDICES)) + { + static BOOL warned; + if (!warned) + { + FIXME("blendMatrixIndices support\n"); + warned = TRUE; + } + } + } + else + { + /* TODO: Support vertex blending in immediate mode draws. No need + * to write a FIXME here, this is done after the general vertex + * declaration decoding. */ + WARN("Vertex blending not supported.\n"); + } + } + else + { + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + static const GLbyte one = 1; + GL_EXTCALL(glWeightbvARB(1, &one)); + checkGLcall("glWeightbvARB(gl_info->max_blends, weights)"); + } + } + + /* Point Size ----------------------------------------------*/ + if (si->use_map & (1u << WINED3D_FFP_PSIZE)) + { + /* no such functionality in the fixed function GL pipeline */ + TRACE("Cannot change ptSize here in openGl\n"); + /* TODO: Implement this function in using shaders if they are available */ + } + + /* Vertex Pointers -----------------------------------------*/ + if (si->use_map & (1u << WINED3D_FFP_POSITION)) + { + e = &si->elements[WINED3D_FFP_POSITION]; + + if (curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = e->data.buffer_object; + } + + TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glVertexPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glVertexPointer(...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_VERTEX_ARRAY); + checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)"); + } + + /* Normals -------------------------------------------------*/ + if (si->use_map & (1u << WINED3D_FFP_NORMAL)) + { + e = &si->elements[WINED3D_FFP_NORMAL]; + + if (curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = e->data.buffer_object; + } + + TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glNormalPointer(e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glNormalPointer(...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_NORMAL_ARRAY); + checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)"); + + } + else + { + gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0); + checkGLcall("glNormal3f(0, 0, 0)"); + } + + /* Diffuse Colour --------------------------------------------*/ + if (si->use_map & (1u << WINED3D_FFP_DIFFUSE)) + { + e = &si->elements[WINED3D_FFP_DIFFUSE]; + + if (curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = e->data.buffer_object; + } + + TRACE("glColorPointer(%#x, %#x %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glColorPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_COLOR_ARRAY); + checkGLcall("glEnableClientState(GL_COLOR_ARRAY)"); + + } + else + { + gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + checkGLcall("glColor4f(1, 1, 1, 1)"); + } + + /* Specular Colour ------------------------------------------*/ + if (si->use_map & (1u << WINED3D_FFP_SPECULAR)) + { + TRACE("setting specular colour\n"); + + e = &si->elements[WINED3D_FFP_SPECULAR]; + + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GLenum type = e->format->gl_vtx_type; + GLint format = e->format->gl_vtx_format; + + if (curVBO != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + curVBO = e->data.buffer_object; + } + + if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA)) + { + /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha + * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function + * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts + * 4 component secondary colors use it + */ + TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(format, type, ...)"); + } + else + { + switch(type) + { + case GL_UNSIGNED_BYTE: + TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)"); + break; + + default: + FIXME("Add 4 component specular color pointers for type %x\n", type); + /* Make sure that the right color component is dropped */ + TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(3, type, ...)"); + } + } + gl_info->gl_ops.gl.p_glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + else + { + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); + checkGLcall("glSecondaryColor3fEXT(0, 0, 0)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + + /* Texture coords -------------------------------------------*/ + load_tex_coords(context, si, &curVBO, state); +} + static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - if (isStateDirty(context, STATE_VDECL)) - return; - context_update_stream_sources(context, state); + BOOL load_numbered = context->d3d_info->ffp_generic_attributes + || (use_vs(state) && !context->use_immediate_mode_draw); + BOOL load_named = !context->d3d_info->ffp_generic_attributes + && !use_vs(state) && !context->use_immediate_mode_draw; + + if (isStateDirty(context, STATE_VDECL)) return; + if (context->numberedArraysLoaded && !load_numbered) + { + unload_numbered_arrays(context); + context->numberedArraysLoaded = FALSE; + context->numbered_array_mask = 0; + } + else if (context->namedArraysLoaded) + { + unload_vertex_data(context->gl_info); + context->namedArraysLoaded = FALSE; + } + + if (load_numbered) + { + TRACE("Loading numbered arrays\n"); + load_numbered_arrays(context, &context->stream_info, state); + context->numberedArraysLoaded = TRUE; + } + else if (load_named) + { + TRACE("Loading vertex data\n"); + load_vertex_data(context, &context->stream_info, state); + context->namedArraysLoaded = TRUE; + } } static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { if (isStateDirty(context, STATE_STREAMSRC)) return; - context_update_stream_sources(context, state); + streamsrc(context, state, STATE_STREAMSRC); } static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4003,18 +4682,30 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine } } -static void get_viewports(struct wined3d_context *context, const struct wined3d_state *state, - unsigned int viewport_count, struct wined3d_viewport *viewports) +static void get_viewport(struct wined3d_context *context, const struct wined3d_state *state, + struct wined3d_viewport *viewport) { const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil; const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; - unsigned int width, height, i; + unsigned int width, height; - for (i = 0; i < viewport_count; ++i) - viewports[i] = state->viewports[i]; + *viewport = state->viewport; + + if (target) + { + if (context->d3d_info->wined3d_creation_flags & WINED3D_LIMIT_VIEWPORT) + { + if (viewport->width > target->width) + viewport->width = target->width; + if (viewport->height > target->height) + viewport->height = target->height; + } + } - /* Note: GL uses a lower left origin while DirectX uses upper left. This - * is reversed when using offscreen rendering. */ + /* + * Note: GL requires lower left, DirectX supplies upper left. This is + * reversed when using offscreen rendering. + */ if (context->render_offscreen) return; @@ -4032,53 +4723,22 @@ static void get_viewports(struct wined3d_context *context, const struct wined3d_ return; } - for (i = 0; i < viewport_count; ++i) - viewports[i].y = height - (viewports[i].y + viewports[i].height); + viewport->y = height - (viewport->y + viewport->height); } static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS]; - - if (gl_info->supported[ARB_VIEWPORT_ARRAY]) - { - GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS]; - GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS]; + struct wined3d_viewport vp; - unsigned int i, reset_count = 0; + get_viewport(context, state, &vp); - get_viewports(context, state, state->viewport_count, vp); - for (i = 0; i < state->viewport_count; ++i) - { - depth_ranges[i * 2] = vp[i].min_z; - depth_ranges[i * 2 + 1] = vp[i].max_z; - - viewports[i * 4] = vp[i].x; - viewports[i * 4 + 1] = vp[i].y; - viewports[i * 4 + 2] = vp[i].width; - viewports[i * 4 + 3] = vp[i].height; - } - - if (context->viewport_count > state->viewport_count) - reset_count = context->viewport_count - state->viewport_count; - - if (reset_count) - { - memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges)); - memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports)); - } + gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); - GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges)); - GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports)); - context->viewport_count = state->viewport_count; - } + if (gl_info->supported[ARB_VIEWPORT_ARRAY]) + GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height)); else - { - get_viewports(context, state, 1, vp); - gl_info->gl_ops.gl.p_glDepthRange(vp[0].min_z, vp[0].max_z); - gl_info->gl_ops.gl.p_glViewport(vp[0].x, vp[0].y, vp[0].width, vp[0].height); - } + gl_info->gl_ops.gl.p_glViewport(vp.x, vp.y, vp.width, vp.height); checkGLcall("setting clip space and viewport"); } @@ -4089,39 +4749,16 @@ static void viewport_miscpart_cc(struct wined3d_context *context, float pixel_center_offset = context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f; const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS]; - GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS]; - GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS]; - unsigned int i, reset_count = 0; - - get_viewports(context, state, state->viewport_count, vp); - - GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE)); - - for (i = 0; i < state->viewport_count; ++i) - { - depth_ranges[i * 2] = vp[i].min_z; - depth_ranges[i * 2 + 1] = vp[i].max_z; - - viewports[i * 4] = vp[i].x + pixel_center_offset; - viewports[i * 4 + 1] = vp[i].y + pixel_center_offset; - viewports[i * 4 + 2] = vp[i].width; - viewports[i * 4 + 3] = vp[i].height; - } - - if (context->viewport_count > state->viewport_count) - reset_count = context->viewport_count - state->viewport_count; + struct wined3d_viewport vp; - if (reset_count) - { - memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges)); - memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports)); - } + get_viewport(context, state, &vp); + vp.x += pixel_center_offset; + vp.y += pixel_center_offset; - GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges)); - GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports)); - context->viewport_count = state->viewport_count; + gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); + GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE)); + GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height)); checkGLcall("setting clip space and viewport"); } @@ -4262,53 +4899,27 @@ static void light(struct wined3d_context *context, const struct wined3d_state *s static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int height = 0; - const RECT *r; + const RECT *r = &state->scissor_rect; /* Warning: glScissor uses window coordinates, not viewport coordinates, * so our viewport correction does not apply. Warning2: Even in windowed * mode the coords are relative to the window, not the screen. */ + TRACE("Setting new scissor rect to %s.\n", wine_dbgstr_rect(r)); - if (!context->render_offscreen) - { - const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; - unsigned int width; - - wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height); - } - - if (gl_info->supported[ARB_VIEWPORT_ARRAY]) + if (context->render_offscreen) { - GLint sr[4 * WINED3D_MAX_VIEWPORTS]; - unsigned int i, reset_count = 0; - - for (i = 0; i < state->scissor_rect_count; ++i) - { - r = &state->scissor_rects[i]; - - sr[i * 4] = r->left; - sr[i * 4 + 1] = height ? height - r->top : r->top; - sr[i * 4 + 2] = r->right - r->left; - sr[i * 4 + 3] = r->bottom - r->top; - } - - if (context->scissor_rect_count > state->scissor_rect_count) - reset_count = context->scissor_rect_count - state->scissor_rect_count; - - if (reset_count) - memset(&sr[state->scissor_rect_count * 4], 0, reset_count * 4 * sizeof(GLint)); - - GL_EXTCALL(glScissorArrayv(0, state->scissor_rect_count + reset_count, sr)); - checkGLcall("glScissorArrayv"); - context->scissor_rect_count = state->scissor_rect_count; + gl_info->gl_ops.gl.p_glScissor(r->left, r->top, r->right - r->left, r->bottom - r->top); } else { - r = &state->scissor_rects[0]; - gl_info->gl_ops.gl.p_glScissor(r->left, height ? height - r->top : r->top, - r->right - r->left, r->bottom - r->top); - checkGLcall("glScissor"); + const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; + UINT height; + UINT width; + + wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height); + gl_info->gl_ops.gl.p_glScissor(r->left, height - r->bottom, r->right - r->left, r->bottom - r->top); } + checkGLcall("glScissor"); } static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4327,23 +4938,7 @@ static void indexbuffer(struct wined3d_context *context, const struct wined3d_st } } -static void depth_clip(const struct wined3d_rasterizer_state *r, const struct wined3d_gl_info *gl_info) -{ - if (!gl_info->supported[ARB_DEPTH_CLAMP]) - { - if (r && !r->desc.depth_clip) - FIXME("Depth clamp not supported by this GL implementation.\n"); - return; - } - - if (r && !r->desc.depth_clip) - gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP); - else - gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP); - checkGLcall("depth clip"); -} - -static void rasterizer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +static void frontface(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; GLenum mode; @@ -4354,10 +4949,9 @@ static void rasterizer(struct wined3d_context *context, const struct wined3d_sta gl_info->gl_ops.gl.p_glFrontFace(mode); checkGLcall("glFrontFace"); - depth_clip(state->rasterizer_state, gl_info); } -static void rasterizer_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +static void frontface_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; GLenum mode; @@ -4366,7 +4960,6 @@ static void rasterizer_cc(struct wined3d_context *context, const struct wined3d_ gl_info->gl_ops.gl.p_glFrontFace(mode); checkGLcall("glFrontFace"); - depth_clip(state->rasterizer_state, gl_info); } static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4536,8 +5129,8 @@ const struct StateEntryTemplate misc_state_template[] = { STATE_BLEND, { STATE_BLEND, state_blend_object }, WINED3D_GL_EXT_NONE }, { STATE_STREAMSRC, { STATE_STREAMSRC, streamsrc }, WINED3D_GL_EXT_NONE }, { STATE_VDECL, { STATE_VDECL, vdecl_miscpart }, WINED3D_GL_EXT_NONE }, - { STATE_RASTERIZER, { STATE_RASTERIZER, rasterizer_cc }, ARB_CLIP_CONTROL }, - { STATE_RASTERIZER, { STATE_RASTERIZER, rasterizer }, WINED3D_GL_EXT_NONE }, + { STATE_FRONTFACE, { STATE_FRONTFACE, frontface_cc }, ARB_CLIP_CONTROL }, + { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE }, { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE }, { STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, state_nop }, ARB_CLIP_CONTROL }, { STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, psorigin }, WINED3D_GL_VERSION_2_0 }, @@ -4630,7 +5223,7 @@ const struct StateEntryTemplate misc_state_template[] = { STATE_RENDER(WINED3D_RS_STENCILFUNC), { STATE_RENDER(WINED3D_RS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_STENCILREF), { STATE_RENDER(WINED3D_RS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_STENCILMASK), { STATE_RENDER(WINED3D_RS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), state_stencilwrite2s_ext}, EXT_STENCIL_TWO_SIDE }, + { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE }, { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3D_RS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL), { STATE_RENDER(WINED3D_RS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, @@ -4697,6 +5290,8 @@ const struct StateEntryTemplate misc_state_template[] = { STATE_RENDER(WINED3D_RS_DEPTHBIAS), { STATE_RENDER(WINED3D_RS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_DEPTHBIASCLAMP), { STATE_RENDER(WINED3D_RS_DEPTHBIAS), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_ZVISIBLE), { STATE_RENDER(WINED3D_RS_ZVISIBLE), state_zvisible }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3D_RS_DEPTHCLIP), { STATE_RENDER(WINED3D_RS_DEPTHCLIP), state_depthclip }, ARB_DEPTH_CLAMP }, + { STATE_RENDER(WINED3D_RS_DEPTHCLIP), { STATE_RENDER(WINED3D_RS_DEPTHCLIP), state_depthclip_w }, WINED3D_GL_EXT_NONE }, /* Samplers */ { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE }, @@ -5055,6 +5650,7 @@ static const struct StateEntryTemplate vp_ffp_states[] = { STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3D_RS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3D_RS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3D_RS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3D_RS_VERTEXBLEND), { STATE_RENDER(WINED3D_RS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND }, { STATE_RENDER(WINED3D_RS_VERTEXBLEND), { STATE_RENDER(WINED3D_RS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_POINTSIZE), { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, @@ -5227,7 +5823,7 @@ static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3 caps->xyzrhw = FALSE; caps->ffp_generic_attributes = FALSE; caps->max_active_lights = gl_info->limits.lights; - caps->max_vertex_blend_matrices = 1; + caps->max_vertex_blend_matrices = gl_info->limits.blends; caps->max_vertex_blend_matrix_index = 0; caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS | WINED3DVTXPCAPS_MATERIALSOURCE7 @@ -5485,7 +6081,7 @@ static void validate_state_table(struct StateEntry *state_table) STATE_VIEWPORT, STATE_LIGHT_TYPE, STATE_SCISSORRECT, - STATE_RASTERIZER, + STATE_FRONTFACE, STATE_POINTSPRITECOORDORIGIN, STATE_BASEVERTEXINDEX, STATE_FRAMEBUFFER, diff --git a/dll/directx/wine/wined3d/stateblock.c b/dll/directx/wine/wined3d/stateblock.c index 397ddaac95c..c9b3527d891 100644 --- a/dll/directx/wine/wined3d/stateblock.c +++ b/dll/directx/wine/wined3d/stateblock.c @@ -94,6 +94,7 @@ static const DWORD pixel_states_render[] = WINED3D_RS_ZENABLE, WINED3D_RS_ZFUNC, WINED3D_RS_ZWRITEENABLE, + WINED3D_RS_DEPTHCLIP, }; static const DWORD pixel_states_texture[] = @@ -814,33 +815,20 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock) stateblock->state.material = src_state->material; } - assert(src_state->viewport_count <= 1); - if (stateblock->changed.viewport - && (src_state->viewport_count != stateblock->state.viewport_count - || memcmp(src_state->viewports, stateblock->state.viewports, - src_state->viewport_count * sizeof(*stateblock->state.viewports)))) + && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport))) { - TRACE("Updating viewports.\n"); + TRACE("Updating viewport.\n"); - if ((stateblock->state.viewport_count = src_state->viewport_count)) - memcpy(stateblock->state.viewports, src_state->viewports, sizeof(src_state->viewports)); - else - memset(stateblock->state.viewports, 0, sizeof(*stateblock->state.viewports)); + stateblock->state.viewport = src_state->viewport; } - if (stateblock->changed.scissorRect - && (src_state->scissor_rect_count != stateblock->state.scissor_rect_count - || memcmp(src_state->scissor_rects, stateblock->state.scissor_rects, - src_state->scissor_rect_count * sizeof(*stateblock->state.scissor_rects)))) + if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect, + &stateblock->state.scissor_rect, sizeof(stateblock->state.scissor_rect))) { - TRACE("Updating scissor rects.\n"); + TRACE("Updating scissor rect.\n"); - if ((stateblock->state.scissor_rect_count = src_state->scissor_rect_count)) - memcpy(stateblock->state.scissor_rects, src_state->scissor_rects, - src_state->scissor_rect_count * sizeof(*src_state->scissor_rects)); - else - SetRectEmpty(stateblock->state.scissor_rects); + stateblock->state.scissor_rect = src_state->scissor_rect; } map = stateblock->changed.streamSource; @@ -1072,11 +1060,10 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock) wined3d_device_set_material(device, &stateblock->state.material); if (stateblock->changed.viewport) - wined3d_device_set_viewports(device, stateblock->state.viewport_count, stateblock->state.viewports); + wined3d_device_set_viewport(device, &stateblock->state.viewport); if (stateblock->changed.scissorRect) - wined3d_device_set_scissor_rects(device, stateblock->state.scissor_rect_count, - stateblock->state.scissor_rects); + wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect); map = stateblock->changed.streamSource; for (i = 0; map; map >>= 1, ++i) @@ -1259,6 +1246,7 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d state->render_states[WINED3D_RS_DEPTHBIAS] = 0; tmpfloat.f = 0.0f; state->render_states[WINED3D_RS_DEPTHBIASCLAMP] = tmpfloat.d; + state->render_states[WINED3D_RS_DEPTHCLIP] = TRUE; state->render_states[WINED3D_RS_WRAP8] = 0; state->render_states[WINED3D_RS_WRAP9] = 0; state->render_states[WINED3D_RS_WRAP10] = 0; diff --git a/dll/directx/wine/wined3d/surface.c b/dll/directx/wine/wined3d/surface.c index baad32e1daf..ae32235a9e6 100644 --- a/dll/directx/wine/wined3d/surface.c +++ b/dll/directx/wine/wined3d/surface.c @@ -36,6 +36,208 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER; +struct blt_info +{ + GLenum binding; + GLenum bind_target; + enum wined3d_gl_resource_type tex_type; + struct wined3d_vec3 texcoords[4]; +}; + +struct float_rect +{ + float l; + float t; + float r; + float b; +}; + +static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float_rect *f) +{ + f->l = ((r->left * 2.0f) / w) - 1.0f; + f->t = ((r->top * 2.0f) / h) - 1.0f; + f->r = ((r->right * 2.0f) / w) - 1.0f; + f->b = ((r->bottom * 2.0f) / h) - 1.0f; +} + +static void texture2d_get_blt_info(const struct wined3d_texture *texture, + unsigned int sub_resource_idx, const RECT *rect, struct blt_info *info) +{ + struct wined3d_vec3 *coords = info->texcoords; + struct float_rect f; + unsigned int level; + GLenum target; + GLsizei w, h; + + level = sub_resource_idx % texture->level_count; + w = wined3d_texture_get_level_pow2_width(texture, level); + h = wined3d_texture_get_level_pow2_height(texture, level); + target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); + + switch (target) + { + default: + FIXME("Unsupported texture target %#x.\n", target); + /* Fall back to GL_TEXTURE_2D */ + case GL_TEXTURE_2D: + info->binding = GL_TEXTURE_BINDING_2D; + info->bind_target = GL_TEXTURE_2D; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_2D; + coords[0].x = (float)rect->left / w; + coords[0].y = (float)rect->top / h; + coords[0].z = 0.0f; + + coords[1].x = (float)rect->right / w; + coords[1].y = (float)rect->top / h; + coords[1].z = 0.0f; + + coords[2].x = (float)rect->left / w; + coords[2].y = (float)rect->bottom / h; + coords[2].z = 0.0f; + + coords[3].x = (float)rect->right / w; + coords[3].y = (float)rect->bottom / h; + coords[3].z = 0.0f; + break; + + case GL_TEXTURE_RECTANGLE_ARB: + info->binding = GL_TEXTURE_BINDING_RECTANGLE_ARB; + info->bind_target = GL_TEXTURE_RECTANGLE_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_RECT; + coords[0].x = rect->left; coords[0].y = rect->top; coords[0].z = 0.0f; + coords[1].x = rect->right; coords[1].y = rect->top; coords[1].z = 0.0f; + coords[2].x = rect->left; coords[2].y = rect->bottom; coords[2].z = 0.0f; + coords[3].x = rect->right; coords[3].y = rect->bottom; coords[3].z = 0.0f; + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = 1.0f; coords[0].y = -f.t; coords[0].z = -f.l; + coords[1].x = 1.0f; coords[1].y = -f.t; coords[1].z = -f.r; + coords[2].x = 1.0f; coords[2].y = -f.b; coords[2].z = -f.l; + coords[3].x = 1.0f; coords[3].y = -f.b; coords[3].z = -f.r; + break; + + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = -1.0f; coords[0].y = -f.t; coords[0].z = f.l; + coords[1].x = -1.0f; coords[1].y = -f.t; coords[1].z = f.r; + coords[2].x = -1.0f; coords[2].y = -f.b; coords[2].z = f.l; + coords[3].x = -1.0f; coords[3].y = -f.b; coords[3].z = f.r; + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = f.l; coords[0].y = 1.0f; coords[0].z = f.t; + coords[1].x = f.r; coords[1].y = 1.0f; coords[1].z = f.t; + coords[2].x = f.l; coords[2].y = 1.0f; coords[2].z = f.b; + coords[3].x = f.r; coords[3].y = 1.0f; coords[3].z = f.b; + break; + + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = f.l; coords[0].y = -1.0f; coords[0].z = -f.t; + coords[1].x = f.r; coords[1].y = -1.0f; coords[1].z = -f.t; + coords[2].x = f.l; coords[2].y = -1.0f; coords[2].z = -f.b; + coords[3].x = f.r; coords[3].y = -1.0f; coords[3].z = -f.b; + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = f.l; coords[0].y = -f.t; coords[0].z = 1.0f; + coords[1].x = f.r; coords[1].y = -f.t; coords[1].z = 1.0f; + coords[2].x = f.l; coords[2].y = -f.b; coords[2].z = 1.0f; + coords[3].x = f.r; coords[3].y = -f.b; coords[3].z = 1.0f; + break; + + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; + info->tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE; + cube_coords_float(rect, w, h, &f); + + coords[0].x = -f.l; coords[0].y = -f.t; coords[0].z = -1.0f; + coords[1].x = -f.r; coords[1].y = -f.t; coords[1].z = -1.0f; + coords[2].x = -f.l; coords[2].y = -f.b; coords[2].z = -1.0f; + coords[3].x = -f.r; coords[3].y = -f.b; coords[3].z = -1.0f; + break; + } +} + +/* Context activation is done by the caller. */ +void draw_textured_quad(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect, + enum wined3d_texture_filter_type filter) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct blt_info info; + + texture2d_get_blt_info(texture, sub_resource_idx, src_rect, &info); + + gl_info->gl_ops.gl.p_glEnable(info.bind_target); + checkGLcall("glEnable(bind_target)"); + + context_bind_texture(context, info.bind_target, texture->texture_rgb.name); + + /* Filtering for StretchRect */ + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAG_FILTER, wined3d_gl_mag_filter(filter)); + checkGLcall("glTexParameteri"); + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MIN_FILTER, + wined3d_gl_min_mip_filter(filter, WINED3D_TEXF_NONE)); + checkGLcall("glTexParameteri"); + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + checkGLcall("glTexEnvi"); + + /* Draw a quad */ + gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP); + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[0].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->top); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[1].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->top); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[2].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->bottom); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[3].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->bottom); + gl_info->gl_ops.gl.p_glEnd(); + + /* Unbind the texture */ + context_bind_texture(context, info.bind_target, 0); + + /* We changed the filtering settings on the texture. Inform the + * container about this to get the filters reset properly next draw. */ + texture->texture_rgb.sampler_desc.mag_filter = WINED3D_TEXF_POINT; + texture->texture_rgb.sampler_desc.min_filter = WINED3D_TEXF_POINT; + texture->texture_rgb.sampler_desc.mip_filter = WINED3D_TEXF_NONE; + texture->texture_rgb.sampler_desc.srgb_decode = FALSE; +} + /* Works correctly only for <= 4 bpp formats. */ static void get_color_masks(const struct wined3d_format *format, DWORD *masks) { @@ -57,19 +259,24 @@ static BOOL texture2d_is_full_rect(const struct wined3d_texture *texture, unsign return TRUE; } -static void texture2d_depth_blt_fbo(const struct wined3d_device *device, struct wined3d_context *context, - struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, - const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - DWORD dst_location, const RECT *dst_rect) +static void surface_depth_blt_fbo(const struct wined3d_device *device, + struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect, + struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect) { - const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + struct wined3d_texture *dst_texture = dst_surface->container; + struct wined3d_texture *src_texture = src_surface->container; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; DWORD src_mask, dst_mask; GLbitfield gl_mask; - TRACE("device %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s.\n", device, - src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), - dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect)); + TRACE("device %p\n", device); + TRACE("src_surface %p, src_location %s, src_rect %s,\n", + src_surface, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect)); + TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n", + dst_surface, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect)); src_mask = src_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); dst_mask = dst_texture->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); @@ -95,6 +302,14 @@ static void texture2d_depth_blt_fbo(const struct wined3d_device *device, struct if (src_mask & WINED3DFMT_FLAG_STENCIL) gl_mask |= GL_STENCIL_BUFFER_BIT; + context = context_acquire(device, NULL, 0); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping blit.\n"); + return; + } + /* Make sure the locations are up-to-date. Loading the destination * surface isn't required if the entire surface is overwritten. */ wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, src_location); @@ -103,12 +318,12 @@ static void texture2d_depth_blt_fbo(const struct wined3d_device *device, struct else wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, dst_location); - context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, 0, - &src_texture->resource, src_sub_resource_idx, src_location); + gl_info = context->gl_info; + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, 0, - &dst_texture->resource, dst_sub_resource_idx, dst_location); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, dst_surface, dst_location); context_set_draw_buffer(context, GL_NONE); context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -135,6 +350,11 @@ static void texture2d_depth_blt_fbo(const struct wined3d_device *device, struct gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST); checkGLcall("glBlitFramebuffer()"); + + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); } static BOOL is_multisample_location(const struct wined3d_texture *texture, DWORD location) @@ -148,25 +368,31 @@ static BOOL is_multisample_location(const struct wined3d_texture *texture, DWORD /* Blit between surface locations. Onscreen on different swapchains is not supported. * Depth / stencil is not supported. Context activation is done by the caller. */ -static void texture2d_blt_fbo(const struct wined3d_device *device, struct wined3d_context *context, - enum wined3d_texture_filter_type filter, struct wined3d_texture *src_texture, - unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, - struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, - const RECT *dst_rect) -{ - struct wined3d_texture *required_texture, *restore_texture; - unsigned int required_idx, restore_idx; +static void surface_blt_fbo(const struct wined3d_device *device, + struct wined3d_context *old_ctx, enum wined3d_texture_filter_type filter, + struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in, + struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in) +{ + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + struct wined3d_texture *dst_texture = dst_surface->container; + struct wined3d_texture *src_texture = src_surface->container; const struct wined3d_gl_info *gl_info; + struct wined3d_context *context = old_ctx; + struct wined3d_surface *required_rt, *restore_rt = NULL; + RECT src_rect, dst_rect; GLenum gl_filter; GLenum buffer; - RECT s, d; int i; - TRACE("device %p, context %p, filter %s, src_texture %p, src_sub_resource_idx %u, src_location %s, " - "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s.\n", - device, context, debug_d3dtexturefiltertype(filter), src_texture, src_sub_resource_idx, - wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, - dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect)); + TRACE("device %p, filter %s,\n", device, debug_d3dtexturefiltertype(filter)); + TRACE("src_surface %p, src_location %s, src_rect %s,\n", + src_surface, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect_in)); + TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n", + dst_surface, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect_in)); + + src_rect = *src_rect_in; + dst_rect = *dst_rect_in; switch (filter) { @@ -185,43 +411,31 @@ static void texture2d_blt_fbo(const struct wined3d_device *device, struct wined3 /* Resolve the source surface first if needed. */ if (is_multisample_location(src_texture, src_location) && (src_texture->resource.format->id != dst_texture->resource.format->id - || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) - || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))) + || abs(src_rect.bottom - src_rect.top) != abs(dst_rect.bottom - dst_rect.top) + || abs(src_rect.right - src_rect.left) != abs(dst_rect.right - dst_rect.left))) src_location = WINED3D_LOCATION_RB_RESOLVED; /* Make sure the locations are up-to-date. Loading the destination * surface isn't required if the entire surface is overwritten. (And is * in fact harmful if we're being called by surface_load_location() with * the purpose of loading the destination surface.) */ - wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, src_location); - if (!texture2d_is_full_rect(dst_texture, dst_sub_resource_idx % dst_texture->level_count, dst_rect)) - wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, dst_location); + wined3d_texture_load_location(src_texture, src_sub_resource_idx, old_ctx, src_location); + if (!texture2d_is_full_rect(dst_texture, dst_sub_resource_idx % dst_texture->level_count, &dst_rect)) + wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, old_ctx, dst_location); else - wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, dst_location); + wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, old_ctx, dst_location); - if (src_location == WINED3D_LOCATION_DRAWABLE) - { - required_texture = src_texture; - required_idx = src_sub_resource_idx; - } - else if (dst_location == WINED3D_LOCATION_DRAWABLE) - { - required_texture = dst_texture; - required_idx = dst_sub_resource_idx; - } - else - { - required_texture = NULL; - required_idx = 0; - } + if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface; + else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface; + else required_rt = NULL; - restore_texture = context->current_rt.texture; - restore_idx = context->current_rt.sub_resource_idx; - if (restore_texture != required_texture || restore_idx != required_idx) - context = context_acquire(device, required_texture, required_idx); + restore_rt = context_get_rt_surface(old_ctx); + if (restore_rt != required_rt) + context = context_acquire(device, required_rt ? required_rt->container : NULL, + required_rt ? surface_get_sub_resource_idx(required_rt) : 0); else - restore_texture = NULL; + restore_rt = NULL; if (!context->valid) { @@ -234,40 +448,34 @@ static void texture2d_blt_fbo(const struct wined3d_device *device, struct wined3 if (src_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Source texture %p is onscreen.\n", src_texture); + TRACE("Source surface %p is onscreen.\n", src_surface); buffer = wined3d_texture_get_gl_buffer(src_texture); - s = *src_rect; - wined3d_texture_translate_drawable_coords(src_texture, context->win_handle, &s); - src_rect = &s; + surface_translate_drawable_coords(src_surface, context->win_handle, &src_rect); } else { - TRACE("Source texture %p is offscreen.\n", src_texture); + TRACE("Source surface %p is offscreen.\n", src_surface); buffer = GL_COLOR_ATTACHMENT0; } - context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, - &src_texture->resource, src_sub_resource_idx, NULL, 0, src_location); + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location); gl_info->gl_ops.gl.p_glReadBuffer(buffer); checkGLcall("glReadBuffer()"); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); if (dst_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Destination texture %p is onscreen.\n", dst_texture); + TRACE("Destination surface %p is onscreen.\n", dst_surface); buffer = wined3d_texture_get_gl_buffer(dst_texture); - d = *dst_rect; - wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d); - dst_rect = &d; + surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect); } else { - TRACE("Destination texture %p is offscreen.\n", dst_texture); + TRACE("Destination surface %p is offscreen.\n", dst_surface); buffer = GL_COLOR_ATTACHMENT0; } - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, - &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location); context_set_draw_buffer(context, buffer); context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -279,15 +487,16 @@ static void texture2d_blt_fbo(const struct wined3d_device *device, struct wined3 gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); - gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, - dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, GL_COLOR_BUFFER_BIT, gl_filter); + gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, + dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter); checkGLcall("glBlitFramebuffer()"); - if (dst_location == WINED3D_LOCATION_DRAWABLE && dst_texture->swapchain->front_buffer == dst_texture) + if (wined3d_settings.strict_draw_ordering || (dst_location == WINED3D_LOCATION_DRAWABLE + && dst_texture->swapchain->front_buffer == dst_texture)) gl_info->gl_ops.gl.p_glFlush(); - if (restore_texture) - context_restore(context, restore_texture, restore_idx); + if (restore_rt) + context_restore(context, restore_rt); } static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_gl_info *gl_info, @@ -304,9 +513,6 @@ static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct win if (!(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) return FALSE; - if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) - return FALSE; - switch (blit_op) { case WINED3D_BLIT_OP_COLOR_BLIT: @@ -344,11 +550,12 @@ static BOOL fbo_blitter_supported(enum wined3d_blit_op blit_op, const struct win /* This call just downloads data, the caller is responsible for binding the * correct texture. */ /* Context activation is done by the caller. */ -static void texture2d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, - const struct wined3d_context *context, DWORD dst_location) +static void surface_download_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, + DWORD dst_location) { + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + struct wined3d_texture *texture = surface->container; const struct wined3d_format *format = texture->resource.format; - const struct wined3d_gl_info *gl_info = context->gl_info; struct wined3d_texture_sub_resource *sub_resource; unsigned int dst_row_pitch, dst_slice_pitch; unsigned int src_row_pitch, src_slice_pitch; @@ -358,11 +565,10 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in GLenum target; void *mem; - /* Only support read back of converted P8 textures. */ + /* Only support read back of converted P8 surfaces. */ if (texture->flags & WINED3D_TEXTURE_CONVERTED && format->id != WINED3DFMT_P8_UINT && !format->download) { - ERR("Trying to read back converted texture %p, %u with format %s.\n", - texture, sub_resource_idx, debug_d3dformat(format->id)); + ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id)); return; } @@ -382,7 +588,7 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) ERR("Array texture %p uses NP2 emulation.\n", texture); - WARN_(d3d_perf)("Downloading all miplevel layers to get the data for a single sub-resource.\n"); + WARN_(d3d_perf)("Downloading all miplevel layers to get the surface data for a single sub-resource.\n"); if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size))) { @@ -425,8 +631,7 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in if (data.buffer_object) ERR("Converted texture %p uses PBO unexpectedly.\n", texture); - WARN_(d3d_perf)("Downloading converted texture %p, %u with format %s.\n", - texture, sub_resource_idx, debug_d3dformat(format->id)); + WARN_(d3d_perf)("Downloading converted surface %p with format %s.\n", surface, debug_d3dformat(format->id)); f = *format; f.byte_count = format->conv_byte_count; @@ -460,16 +665,16 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in if (texture->resource.format_flags & WINED3DFMT_FLAG_COMPRESSED) { - TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n", - texture, sub_resource_idx, level, format->glFormat, format->glType, mem); + TRACE("Downloading compressed surface %p, level %u, format %#x, type %#x, data %p.\n", + surface, level, format->glFormat, format->glType, mem); GL_EXTCALL(glGetCompressedTexImage(target, level, mem)); checkGLcall("glGetCompressedTexImage"); } else { - TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n", - texture, sub_resource_idx, level, format->glFormat, format->glType, mem); + TRACE("Downloading surface %p, level %u, format %#x, type %#x, data %p.\n", + surface, level, format->glFormat, format->glType, mem); gl_info->gl_ops.gl.p_glGetTexImage(target, level, format->glFormat, format->glType, mem); checkGLcall("glGetTexImage"); @@ -568,6 +773,291 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in heap_free(temporary_mem); } +/* This call just uploads data, the caller is responsible for binding the + * correct texture. */ +/* Context activation is done by the caller. */ +void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, + const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, + BOOL srgb, const struct wined3d_const_bo_address *data) +{ + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + struct wined3d_texture *texture = surface->container; + UINT update_w = src_rect->right - src_rect->left; + UINT update_h = src_rect->bottom - src_rect->top; + unsigned int level, layer; + GLenum target; + + TRACE("surface %p, gl_info %p, format %s, src_rect %s, src_pitch %u, dst_point %s, srgb %#x, data {%#x:%p}.\n", + surface, gl_info, debug_d3dformat(format->id), wine_dbgstr_rect(src_rect), src_pitch, + wine_dbgstr_point(dst_point), srgb, data->buffer_object, data->addr); + + if (texture->sub_resources[sub_resource_idx].map_count) + { + WARN("Uploading a surface that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n"); + texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM; + } + + if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_HEIGHT_SCALE) + { + update_h *= format->height_scale.numerator; + update_h /= format->height_scale.denominator; + } + + if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object)); + checkGLcall("glBindBuffer"); + } + + target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); + level = sub_resource_idx % texture->level_count; + layer = sub_resource_idx / texture->level_count; + + if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) + { + unsigned int dst_row_pitch, dst_slice_pitch; + const BYTE *addr = data->addr; + GLenum internal; + + addr += (src_rect->top / format->block_height) * src_pitch; + addr += (src_rect->left / format->block_width) * format->block_byte_count; + + if (srgb) + internal = format->glGammaInternal; + else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET + && wined3d_resource_is_offscreen(&texture->resource)) + internal = format->rtInternal; + else + internal = format->glInternal; + + wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch); + + TRACE("Uploading compressed data, target %#x, level %u, layer %u, x %d, y %d, w %u, h %u, " + "format %#x, image_size %#x, addr %p.\n", + target, level, layer, dst_point->x, dst_point->y, + update_w, update_h, internal, dst_slice_pitch, addr); + + if (dst_row_pitch == src_pitch) + { + if (target == GL_TEXTURE_2D_ARRAY) + { + GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_point->x, dst_point->y, + layer, update_w, update_h, 1, internal, dst_slice_pitch, addr)); + } + else + { + GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_point->x, dst_point->y, + update_w, update_h, internal, dst_slice_pitch, addr)); + } + } + else + { + UINT row_count = (update_h + format->block_height - 1) / format->block_height; + UINT row, y; + + /* glCompressedTexSubImage2D() ignores pixel store state, so we + * can't use the unpack row length like for glTexSubImage2D. */ + for (row = 0, y = dst_point->y; row < row_count; ++row) + { + if (target == GL_TEXTURE_2D_ARRAY) + { + GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_point->x, y, + layer, update_w, format->block_height, 1, internal, dst_row_pitch, addr)); + } + else + { + GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_point->x, y, + update_w, format->block_height, internal, dst_row_pitch, addr)); + } + + y += format->block_height; + addr += src_pitch; + } + } + checkGLcall("Upload compressed surface data"); + } + else + { + const BYTE *addr = data->addr; + + addr += src_rect->top * src_pitch; + addr += src_rect->left * format->byte_count; + + TRACE("Uploading data, target %#x, level %u, layer %u, x %d, y %d, w %u, h %u, " + "format %#x, type %#x, addr %p.\n", + target, level, layer, dst_point->x, dst_point->y, + update_w, update_h, format->glFormat, format->glType, addr); + + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_pitch / format->byte_count); + if (target == GL_TEXTURE_2D_ARRAY) + { + GL_EXTCALL(glTexSubImage3D(target, level, dst_point->x, dst_point->y, + layer, update_w, update_h, 1, format->glFormat, format->glType, addr)); + } + else + { + gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_point->x, dst_point->y, + update_w, update_h, format->glFormat, format->glType, addr); + } + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + checkGLcall("Upload surface data"); + } + + if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); + checkGLcall("glBindBuffer"); + } + + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); + + if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE) + { + struct wined3d_device *device = texture->resource.device; + unsigned int i; + + for (i = 0; i < device->context_count; ++i) + { + context_surface_update(device->contexts[i], surface); + } + } +} + +static HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, + struct wined3d_surface *src_surface, const RECT *src_rect) +{ + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + struct wined3d_texture *src_texture = src_surface->container; + struct wined3d_texture *dst_texture = dst_surface->container; + unsigned int src_row_pitch, src_slice_pitch; + const struct wined3d_gl_info *gl_info; + unsigned int src_level, dst_level; + struct wined3d_context *context; + struct wined3d_bo_address data; + UINT update_w, update_h; + + TRACE("dst_surface %p, dst_point %s, src_surface %p, src_rect %s.\n", + dst_surface, wine_dbgstr_point(dst_point), + src_surface, wine_dbgstr_rect(src_rect)); + + context = context_acquire(dst_texture->resource.device, NULL, 0); + gl_info = context->gl_info; + + /* Only load the surface for partial updates. For newly allocated texture + * the texture wouldn't be the current location, and we'd upload zeroes + * just to overwrite them again. */ + update_w = src_rect->right - src_rect->left; + update_h = src_rect->bottom - src_rect->top; + dst_level = dst_sub_resource_idx % dst_texture->level_count; + if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level) + && update_h == wined3d_texture_get_level_height(dst_texture, dst_level)) + wined3d_texture_prepare_texture(dst_texture, context, FALSE); + else + wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE); + + src_level = src_sub_resource_idx % src_texture->level_count; + wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data, + src_texture->sub_resources[src_sub_resource_idx].locations); + wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch); + + wined3d_surface_upload_data(dst_surface, gl_info, src_texture->resource.format, src_rect, + src_row_pitch, dst_point, FALSE, wined3d_const_bo_address(&data)); + + context_release(context); + + wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); + + return WINED3D_OK; +} + +/* In D3D the depth stencil dimensions have to be greater than or equal to the + * render target dimensions. With FBOs, the dimensions have to be an exact match. */ +/* TODO: We should synchronize the renderbuffer's content with the texture's content. */ +/* Context activation is done by the caller. */ +void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_rendertarget_info *rt) +{ + unsigned int sub_resource_idx, width, height, level; + struct wined3d_renderbuffer_entry *entry; + const struct wined3d_texture *texture; + const struct wined3d_gl_info *gl_info; + unsigned int src_width, src_height; + GLuint renderbuffer = 0; + + texture = surface->container; + gl_info = &texture->resource.device->adapter->gl_info; + sub_resource_idx = surface_get_sub_resource_idx(surface); + level = sub_resource_idx % texture->level_count; + + if (rt && rt->resource->format->id != WINED3DFMT_NULL) + { + struct wined3d_texture *rt_texture; + unsigned int rt_level; + + if (rt->resource->type == WINED3D_RTYPE_BUFFER) + { + FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type)); + return; + } + rt_texture = wined3d_texture_from_resource(rt->resource); + rt_level = rt->sub_resource_idx % rt_texture->level_count; + + width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level); + height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level); + } + else + { + width = wined3d_texture_get_level_pow2_width(texture, level); + height = wined3d_texture_get_level_pow2_height(texture, level); + } + + src_width = wined3d_texture_get_level_pow2_width(texture, level); + src_height = wined3d_texture_get_level_pow2_height(texture, level); + + /* A depth stencil smaller than the render target is not valid */ + if (width > src_width || height > src_height) return; + + /* Remove any renderbuffer set if the sizes match */ + if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] + || (width == src_width && height == src_height)) + { + surface->current_renderbuffer = NULL; + return; + } + + /* Look if we've already got a renderbuffer of the correct dimensions */ + LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry) + { + if (entry->width == width && entry->height == height) + { + renderbuffer = entry->id; + surface->current_renderbuffer = entry; + break; + } + } + + if (!renderbuffer) + { + gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer); + gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, + texture->resource.format->glInternal, width, height); + + entry = heap_alloc(sizeof(*entry)); + entry->width = width; + entry->height = height; + entry->id = renderbuffer; + list_add_head(&surface->renderbuffers, &entry->entry); + + surface->current_renderbuffer = entry; + } + + checkGLcall("set_compatible_renderbuffer"); +} + /* See also float_16_to_32() in wined3d_private.h */ static inline unsigned short float_32_to_16(const float *in) { @@ -990,6 +1480,7 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr const struct wined3d_format *src_format = src_texture->resource.format; struct wined3d_device *device = src_texture->resource.device; const struct d3dfmt_converter_desc *conv = NULL; + const struct wined3d_gl_info *gl_info = NULL; unsigned int src_row_pitch, src_slice_pitch; struct wined3d_context *context = NULL; struct wined3d_texture *dst_texture; @@ -1027,7 +1518,10 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr } if (device->d3d_initialized) + { context = context_acquire(device, NULL, 0); + gl_info = context->gl_info; + } map_binding = src_texture->resource.map_binding; if (!wined3d_texture_load_location(src_texture, sub_resource_idx, context, map_binding)) @@ -1061,14 +1555,15 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr } else { - struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1}; + RECT src_rect = {0, 0, desc.width, desc.height}; + POINT dst_point = {0, 0}; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_texture(dst_texture, context, FALSE); wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE); - wined3d_texture_upload_data(dst_texture, 0, context, src_format, &src_box, - wined3d_const_bo_address(&src_data), src_row_pitch, src_slice_pitch, 0, 0, 0, FALSE); + wined3d_surface_upload_data(dst_texture->sub_resources[0].u.surface, gl_info, src_format, + &src_rect, src_row_pitch, &dst_point, FALSE, wined3d_const_bo_address(&src_data)); wined3d_texture_validate_location(dst_texture, 0, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_invalidate_location(dst_texture, 0, ~WINED3D_LOCATION_TEXTURE_RGB); @@ -1080,16 +1575,18 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr return dst_texture; } -static void texture2d_read_from_framebuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, DWORD src_location, DWORD dst_location) +static void read_from_framebuffer(struct wined3d_surface *surface, + struct wined3d_context *old_ctx, DWORD src_location, DWORD dst_location) { + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; - struct wined3d_texture *restore_texture; + struct wined3d_context *context = old_ctx; + struct wined3d_surface *restore_rt = NULL; const struct wined3d_gl_info *gl_info; unsigned int row_pitch, slice_pitch; unsigned int width, height, level; struct wined3d_bo_address data; - unsigned int restore_idx; BYTE *row, *top, *bottom; BOOL src_is_upside_down; unsigned int i; @@ -1097,18 +1594,16 @@ static void texture2d_read_from_framebuffer(struct wined3d_texture *texture, uns wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location); - restore_texture = context->current_rt.texture; - restore_idx = context->current_rt.sub_resource_idx; - if (restore_texture != texture || restore_idx != sub_resource_idx) + restore_rt = context_get_rt_surface(old_ctx); + if (restore_rt != surface) context = context_acquire(device, texture, sub_resource_idx); else - restore_texture = NULL; + restore_rt = NULL; gl_info = context->gl_info; if (src_location != texture->resource.draw_binding) { - context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, - &texture->resource, sub_resource_idx, NULL, 0, src_location); + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL, src_location); context_check_fbo_status(context, GL_READ_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); } @@ -1202,8 +1697,8 @@ error: checkGLcall("glBindBuffer"); } - if (restore_texture) - context_restore(context, restore_texture, restore_idx); + if (restore_rt) + context_restore(context, restore_rt); } /* Read the framebuffer contents into a texture. Note that this function @@ -1212,21 +1707,22 @@ error: * * Context activation is done by the caller. This function may temporarily * switch to a different context and restore the original one before return. */ -void texture2d_load_fb_texture(struct wined3d_texture *texture, - unsigned int sub_resource_idx, BOOL srgb, struct wined3d_context *context) +void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct wined3d_context *old_ctx) { + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; - struct wined3d_texture *restore_texture; const struct wined3d_gl_info *gl_info; - unsigned int restore_idx, level; + struct wined3d_context *context = old_ctx; + struct wined3d_surface *restore_rt = NULL; + unsigned int level; GLenum target; - restore_texture = context->current_rt.texture; - restore_idx = context->current_rt.sub_resource_idx; - if (restore_texture != texture || restore_idx != sub_resource_idx) + restore_rt = context_get_rt_surface(old_ctx); + if (restore_rt != surface) context = context_acquire(device, texture, sub_resource_idx); else - restore_texture = NULL; + restore_rt = NULL; gl_info = context->gl_info; device_invalidate_state(device, STATE_FRAMEBUFFER); @@ -1234,7 +1730,7 @@ void texture2d_load_fb_texture(struct wined3d_texture *texture, wined3d_texture_prepare_texture(texture, context, srgb); wined3d_texture_bind_and_dirtify(texture, context, srgb); - TRACE("Reading back offscreen render target %p, %u.\n", texture, sub_resource_idx); + TRACE("Reading back offscreen render target %p.\n", surface); if (wined3d_resource_is_offscreen(&texture->resource)) gl_info->gl_ops.gl.p_glReadBuffer(context_get_offscreen_gl_buffer(context)); @@ -1249,16 +1745,19 @@ void texture2d_load_fb_texture(struct wined3d_texture *texture, wined3d_texture_get_level_height(texture, level)); checkGLcall("glCopyTexSubImage2D"); - if (restore_texture) - context_restore(context, restore_texture, restore_idx); + if (restore_rt) + context_restore(context, restore_rt); } /* Does a direct frame buffer -> texture copy. Stretching is done with single * pixel copy calls. */ -static void fb_copy_to_texture_direct(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - const RECT *dst_rect_in, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - const RECT *src_rect, enum wined3d_texture_filter_type filter) +static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface, + const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter) { + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + struct wined3d_texture *src_texture = src_surface->container; + struct wined3d_texture *dst_texture = dst_surface->container; struct wined3d_device *device = dst_texture->resource.device; unsigned int src_height, src_level, dst_level; const struct wined3d_gl_info *gl_info; @@ -1372,11 +1871,14 @@ static void fb_copy_to_texture_direct(struct wined3d_texture *dst_texture, unsig } /* Uses the hardware to stretch and flip the image */ -static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - const RECT *dst_rect_in, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - const RECT *src_rect, enum wined3d_texture_filter_type filter) +static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface, + const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter) { unsigned int src_width, src_height, src_pow2_width, src_pow2_height, src_level; + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + struct wined3d_texture *src_texture = src_surface->container; + struct wined3d_texture *dst_texture = dst_surface->container; struct wined3d_device *device = dst_texture->resource.device; GLenum src_target, dst_target, texture_target; GLuint src, backup = 0; @@ -1398,7 +1900,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, un /* Activate the Proper context for reading from the source surface, set it up for blitting */ context = context_acquire(device, src_texture, src_sub_resource_idx); gl_info = context->gl_info; - context_apply_ffp_blit_state(context, device); + context_apply_blit_state(context, device); wined3d_texture_load(dst_texture, context, FALSE); offscreen_buffer = context_get_offscreen_gl_buffer(context); @@ -1448,7 +1950,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, un checkGLcall("glEnable(texture_target)"); /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */ - src_texture->sub_resources[src_sub_resource_idx].locations &= ~WINED3D_LOCATION_TEXTURE_RGB; + surface_get_sub_resource(src_surface)->locations &= ~WINED3D_LOCATION_TEXTURE_RGB; } /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag @@ -1644,6 +2146,9 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, un checkGLcall("glDeleteTextures(1, &backup)"); } + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + context_release(context); /* The texture is now most up to date - If the surface is a render target @@ -1652,24 +2157,47 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_texture *dst_texture, un wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); } -static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) +/* Front buffer coordinates are always full screen coordinates, but our GL + * drawable is limited to the window's client area. The sysmem and texture + * copies do have the full screen size. Note that GL has a bottom-left + * origin, while D3D has a top-left origin. */ +void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect) { - struct wined3d_swapchain *src_swapchain, *dst_swapchain; - const struct wined3d_rendertarget_view *rtv; + struct wined3d_texture *texture = surface->container; + POINT offset = {0, 0}; + UINT drawable_height; + RECT windowsize; - TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, " - "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n", - dst_texture, dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), src_texture, src_sub_resource_idx, - wine_dbgstr_rect(src_rect), flags, fx, debug_d3dtexturefiltertype(filter)); + if (!texture->swapchain) + return; - if (dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D) + if (texture == texture->swapchain->front_buffer) { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_texture->resource.type)); - return WINED3DERR_INVALIDCALL; + ScreenToClient(window, &offset); + OffsetRect(rect, offset.x, offset.y); } + GetClientRect(window, &windowsize); + drawable_height = windowsize.bottom - windowsize.top; + + rect->top = drawable_height - rect->top; + rect->bottom = drawable_height - rect->bottom; +} + +static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) +{ + struct wined3d_texture *dst_texture = dst_surface->container; + struct wined3d_device *device = dst_texture->resource.device; + const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]); + struct wined3d_swapchain *src_swapchain, *dst_swapchain; + struct wined3d_texture *src_texture; + + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), + flags, fx, debug_d3dtexturefiltertype(filter)); + /* Get the swapchain. One of the surfaces has to be a primary surface. */ if (!(dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) { @@ -1677,19 +2205,27 @@ static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, return WINED3DERR_INVALIDCALL; } - if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) + dst_swapchain = dst_texture->swapchain; + + if (src_surface) { - WARN("Source resource is not GPU accessible, rejecting GL blit.\n"); - return WINED3DERR_INVALIDCALL; - } + src_texture = src_surface->container; + if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + WARN("Source resource is not GPU accessible, rejecting GL blit.\n"); + return WINED3DERR_INVALIDCALL; + } - src_swapchain = src_texture->swapchain; - dst_swapchain = dst_texture->swapchain; + src_swapchain = src_texture->swapchain; + } + else + { + src_texture = NULL; + src_swapchain = NULL; + } /* Early sort out of cases where no render target is used */ - if (!(rtv = dst_texture->resource.device->fb.render_targets[0]) || (!src_swapchain && !dst_swapchain - && (&src_texture->resource != rtv->resource || src_sub_resource_idx != rtv->sub_resource_idx) - && (&dst_texture->resource != rtv->resource || dst_sub_resource_idx != rtv->sub_resource_idx))) + if (!dst_swapchain && !src_swapchain && src_surface != rt && dst_surface != rt) { TRACE("No surface is render target, not using hardware blit.\n"); return WINED3DERR_INVALIDCALL; @@ -1718,18 +2254,16 @@ static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, if (dst_swapchain) { /* Handled with regular texture -> swapchain blit */ - if (&src_texture->resource == rtv->resource && src_sub_resource_idx == rtv->sub_resource_idx) + if (src_surface == rt) TRACE("Blit from active render target to a swapchain\n"); } - else if (src_swapchain && &dst_texture->resource == rtv->resource - && dst_sub_resource_idx == rtv->sub_resource_idx) + else if (src_swapchain && dst_surface == rt) { FIXME("Implement blit from a swapchain to the active render target\n"); return WINED3DERR_INVALIDCALL; } - if (!dst_swapchain && (src_swapchain || (&src_texture->resource == rtv->resource - && src_sub_resource_idx == rtv->sub_resource_idx))) + if ((src_swapchain || src_surface == rt) && !dst_swapchain) { unsigned int src_level, src_width, src_height; /* Blit from render target to texture */ @@ -1765,21 +2299,19 @@ static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, * back buffer. This is slower than reading line per line, thus not used for flipping * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied * pixel by pixel. */ - src_level = src_sub_resource_idx % src_texture->level_count; + src_level = surface_get_sub_resource_idx(src_surface) % src_texture->level_count; src_width = wined3d_texture_get_level_width(src_texture, src_level); src_height = wined3d_texture_get_level_height(src_texture, src_level); if (!stretchx || dst_rect->right - dst_rect->left > src_width || dst_rect->bottom - dst_rect->top > src_height) { TRACE("No stretching in x direction, using direct framebuffer -> texture copy.\n"); - fb_copy_to_texture_direct(dst_texture, dst_sub_resource_idx, dst_rect, - src_texture, src_sub_resource_idx, src_rect, filter); + fb_copy_to_texture_direct(dst_surface, src_surface, src_rect, dst_rect, filter); } else { TRACE("Using hardware stretching to flip / stretch the texture.\n"); - fb_copy_to_texture_hwstretch(dst_texture, dst_sub_resource_idx, dst_rect, - src_texture, src_sub_resource_idx, src_rect, filter); + fb_copy_to_texture_hwstretch(dst_surface, src_surface, src_rect, dst_rect, filter); } return WINED3D_OK; @@ -1791,9 +2323,12 @@ static HRESULT wined3d_texture_blt_special(struct wined3d_texture *dst_texture, } /* Context activation is done by the caller. */ -BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_resource_idx, +static BOOL surface_load_sysmem(struct wined3d_surface *surface, struct wined3d_context *context, DWORD dst_location) { + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_texture *texture = surface->container; struct wined3d_texture_sub_resource *sub_resource; sub_resource = &texture->sub_resources[sub_resource_idx]; @@ -1803,8 +2338,7 @@ BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_res if (is_multisample_location(texture, WINED3D_LOCATION_TEXTURE_RGB)) { wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_RB_RESOLVED); - texture2d_read_from_framebuffer(texture, sub_resource_idx, context, - WINED3D_LOCATION_RB_RESOLVED, dst_location); + read_from_framebuffer(surface, context, WINED3D_LOCATION_RB_RESOLVED, dst_location); return TRUE; } else @@ -1812,12 +2346,12 @@ BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_res if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - /* Download the sub-resource to system memory. */ + /* Download the surface to system memory. */ if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { wined3d_texture_bind_and_dirtify(texture, context, !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)); - texture2d_download_data(texture, sub_resource_idx, context, dst_location); + surface_download_data(surface, gl_info, dst_location); ++texture->download_count; return TRUE; @@ -1827,23 +2361,23 @@ BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_res if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE)) { - texture2d_read_from_framebuffer(texture, sub_resource_idx, context, - texture->resource.draw_binding, dst_location); + read_from_framebuffer(surface, context, texture->resource.draw_binding, dst_location); return TRUE; } - FIXME("Can't load texture %p, %u with location flags %s into sysmem.\n", - texture, sub_resource_idx, wined3d_debug_location(sub_resource->locations)); + FIXME("Can't load surface %p with location flags %s into sysmem.\n", + surface, wined3d_debug_location(sub_resource->locations)); return FALSE; } /* Context activation is done by the caller. */ -BOOL texture2d_load_drawable(struct wined3d_texture *texture, - unsigned int sub_resource_idx, struct wined3d_context *context) +static BOOL surface_load_drawable(struct wined3d_surface *surface, + struct wined3d_context *context) { - struct wined3d_texture *restore_texture; + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); + struct wined3d_texture *texture = surface->container; + struct wined3d_surface *restore_rt = NULL; struct wined3d_device *device; - unsigned int restore_idx; unsigned int level; RECT r; @@ -1858,55 +2392,57 @@ BOOL texture2d_load_drawable(struct wined3d_texture *texture, if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && wined3d_resource_is_offscreen(&texture->resource)) { - ERR("Trying to load offscreen texture into WINED3D_LOCATION_DRAWABLE.\n"); + ERR("Trying to load offscreen surface into WINED3D_LOCATION_DRAWABLE.\n"); return FALSE; } device = texture->resource.device; - restore_texture = context->current_rt.texture; - restore_idx = context->current_rt.sub_resource_idx; - if (restore_texture != texture || restore_idx != sub_resource_idx) + restore_rt = context_get_rt_surface(context); + if (restore_rt != surface) context = context_acquire(device, texture, sub_resource_idx); else - restore_texture = NULL; + restore_rt = NULL; level = sub_resource_idx % texture->level_count; SetRect(&r, 0, 0, wined3d_texture_get_level_width(texture, level), wined3d_texture_get_level_height(texture, level)); wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, - texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &r, - texture, sub_resource_idx, WINED3D_LOCATION_DRAWABLE, &r, + surface, WINED3D_LOCATION_TEXTURE_RGB, &r, + surface, WINED3D_LOCATION_DRAWABLE, &r, NULL, WINED3D_TEXF_POINT); - if (restore_texture) - context_restore(context, restore_texture, restore_idx); + if (restore_rt) + context_restore(context, restore_rt); return TRUE; } -BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx, +static BOOL surface_load_texture(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) { unsigned int width, height, level, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; const struct wined3d_color_key_conversion *conversion; struct wined3d_texture_sub_resource *sub_resource; - const struct wined3d_format *format; struct wined3d_bo_address data; BYTE *src_mem, *dst_mem = NULL; - struct wined3d_box src_box; + struct wined3d_format format; + POINT dst_point = {0, 0}; + RECT src_rect; BOOL depth; depth = texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL; - sub_resource = &texture->sub_resources[sub_resource_idx]; + sub_resource = surface_get_sub_resource(surface); if (!depth && wined3d_settings.offscreen_rendering_mode != ORM_FBO && wined3d_resource_is_offscreen(&texture->resource) && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE)) { - texture2d_load_fb_texture(texture, sub_resource_idx, srgb, context); + surface_load_fb_texture(surface, srgb, context); return TRUE; } @@ -1914,7 +2450,7 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re level = sub_resource_idx % texture->level_count; width = wined3d_texture_get_level_width(texture, level); height = wined3d_texture_get_level_height(texture, level); - wined3d_box_set(&src_box, 0, 0, width, height, 0, 1); + SetRect(&src_rect, 0, 0, width, height); if (!depth && sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB) && (texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB) @@ -1922,17 +2458,12 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re &texture->resource, WINED3D_LOCATION_TEXTURE_RGB, &texture->resource, WINED3D_LOCATION_TEXTURE_SRGB)) { - RECT src_rect; - - SetRect(&src_rect, 0, 0, width, height); if (srgb) - texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT, - texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect, - texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); else - texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT, - texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect, - texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); return TRUE; } @@ -1943,13 +2474,11 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re DWORD src_location = sub_resource->locations & WINED3D_LOCATION_RB_RESOLVED ? WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE; DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; - RECT src_rect; - SetRect(&src_rect, 0, 0, width, height); if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info, &texture->resource, src_location, &texture->resource, dst_location)) - texture2d_blt_fbo(device, context, WINED3D_TEXF_POINT, texture, sub_resource_idx, - src_location, &src_rect, texture, sub_resource_idx, dst_location, &src_rect); + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location, + &src_rect, surface, dst_location, &src_rect); return TRUE; } @@ -1961,7 +2490,7 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | texture->resource.map_binding)) == WINED3D_LOCATION_TEXTURE_RGB) { - FIXME_(d3d_perf)("Downloading RGB texture %p, %u to reload it as sRGB.\n", texture, sub_resource_idx); + FIXME_(d3d_perf)("Downloading RGB surface %p to reload it as sRGB.\n", surface); wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); } } @@ -1970,7 +2499,7 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re if ((sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | texture->resource.map_binding)) == WINED3D_LOCATION_TEXTURE_SRGB) { - FIXME_(d3d_perf)("Downloading sRGB texture %p, %u to reload it as RGB.\n", texture, sub_resource_idx); + FIXME_(d3d_perf)("Downloading sRGB surface %p to reload it as RGB.\n", surface); wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); } } @@ -1986,25 +2515,54 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re wined3d_texture_bind_and_dirtify(texture, context, srgb); wined3d_texture_get_pitch(texture, level, &src_row_pitch, &src_slice_pitch); - format = texture->resource.format; + format = *texture->resource.format; if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE))) - format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage); + format = *wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage); /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ - if (conversion && sub_resource->buffer_object) +#if !defined(STAGING_CSMT) + if ((format.conv_byte_count || conversion) && texture->sub_resources[sub_resource_idx].buffer_object) +#else /* STAGING_CSMT */ + if ((format.conv_byte_count || conversion) && texture->sub_resources[sub_resource_idx].buffer) +#endif /* STAGING_CSMT */ { - TRACE("Removing the pbo attached to texture %p, %u.\n", texture, sub_resource_idx); + TRACE("Removing the pbo attached to surface %p.\n", surface); wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); wined3d_texture_set_map_binding(texture, WINED3D_LOCATION_SYSMEM); } wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->locations); - if (conversion) + if (format.conv_byte_count) + { + /* This code is entered for texture formats which need a fixup. */ + format.byte_count = format.conv_byte_count; + wined3d_format_calculate_pitch(&format, 1, width, height, &dst_row_pitch, &dst_slice_pitch); + + src_mem = context_map_bo_address(context, &data, src_slice_pitch, + GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ); + if (!(dst_mem = heap_alloc(dst_slice_pitch))) + { + ERR("Out of memory (%u).\n", dst_slice_pitch); + context_release(context); + return FALSE; + } + format.upload(src_mem, dst_mem, src_row_pitch, src_slice_pitch, + dst_row_pitch, dst_slice_pitch, width, height, 1); + src_row_pitch = dst_row_pitch; + context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER); + + data.buffer_object = 0; + data.addr = dst_mem; + } + else if (conversion) { - wined3d_format_calculate_pitch(format, device->surface_alignment, + /* This code is only entered for color keying fixups */ + struct wined3d_palette *palette = NULL; + + wined3d_format_calculate_pitch(&format, device->surface_alignment, width, height, &dst_row_pitch, &dst_slice_pitch); src_mem = context_map_bo_address(context, &data, src_slice_pitch, @@ -2015,18 +2573,19 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re context_release(context); return FALSE; } + if (texture->swapchain && texture->swapchain->palette) + palette = texture->swapchain->palette; conversion->convert(src_mem, src_row_pitch, dst_mem, dst_row_pitch, - width, height, &texture->async.gl_color_key); + width, height, palette, &texture->async.gl_color_key); src_row_pitch = dst_row_pitch; - src_slice_pitch = dst_slice_pitch; context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER); data.buffer_object = 0; data.addr = dst_mem; } - wined3d_texture_upload_data(texture, sub_resource_idx, context, format, &src_box, - wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, 0, 0, 0, srgb); + wined3d_surface_upload_data(surface, gl_info, &format, &src_rect, + src_row_pitch, &dst_point, srgb, wined3d_const_bo_address(&data)); heap_free(dst_mem); @@ -2034,18 +2593,17 @@ BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_re } /* Context activation is done by the caller. */ -BOOL texture2d_load_renderbuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, DWORD dst_location) +static BOOL surface_load_renderbuffer(struct wined3d_surface *surface, struct wined3d_context *context, + DWORD dst_location) { - unsigned int level = sub_resource_idx % texture->level_count; + struct wined3d_texture *texture = surface->container; + unsigned int level = surface_get_sub_resource_idx(surface) % texture->level_count; const RECT rect = {0, 0, wined3d_texture_get_level_width(texture, level), wined3d_texture_get_level_height(texture, level)}; - struct wined3d_texture_sub_resource *sub_resource; - DWORD src_location, locations; + DWORD locations = surface_get_sub_resource(surface)->locations; + DWORD src_location; - sub_resource = &texture->sub_resources[sub_resource_idx]; - locations = sub_resource->locations; if (texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) { FIXME("Unimplemented copy from %s for depth/stencil buffers.\n", @@ -2059,19 +2617,45 @@ BOOL texture2d_load_renderbuffer(struct wined3d_texture *texture, unsigned int s src_location = WINED3D_LOCATION_RB_RESOLVED; else if (locations & WINED3D_LOCATION_TEXTURE_SRGB) src_location = WINED3D_LOCATION_TEXTURE_SRGB; - else if (locations & WINED3D_LOCATION_TEXTURE_RGB) - src_location = WINED3D_LOCATION_TEXTURE_RGB; - else if (locations & WINED3D_LOCATION_DRAWABLE) - src_location = WINED3D_LOCATION_DRAWABLE; - else /* texture2d_blt_fbo() will load the source location if necessary. */ + else /* surface_blt_fbo will load the source location if necessary. */ src_location = WINED3D_LOCATION_TEXTURE_RGB; - texture2d_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT, texture, - sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect); + surface_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT, + surface, src_location, &rect, surface, dst_location, &rect); return TRUE; } +/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ +BOOL surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) +{ + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); + + switch (location) + { + case WINED3D_LOCATION_USER_MEMORY: + case WINED3D_LOCATION_SYSMEM: + case WINED3D_LOCATION_BUFFER: + return surface_load_sysmem(surface, context, location); + + case WINED3D_LOCATION_DRAWABLE: + return surface_load_drawable(surface, context); + + case WINED3D_LOCATION_RB_RESOLVED: + case WINED3D_LOCATION_RB_MULTISAMPLE: + return surface_load_renderbuffer(surface, context, location); + + case WINED3D_LOCATION_TEXTURE_RGB: + case WINED3D_LOCATION_TEXTURE_SRGB: + return surface_load_texture(surface, context, + location == WINED3D_LOCATION_TEXTURE_SRGB); + + default: + ERR("Don't know how to handle location %#x.\n", location); + return FALSE; + } +} + /* Context activation is done by the caller. */ static void fbo_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context) { @@ -2095,27 +2679,16 @@ static void fbo_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de } static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - 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, + struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, + const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) { - struct wined3d_resource *src_resource, *dst_resource; + struct wined3d_resource *src_resource = &src_surface->container->resource; + struct wined3d_resource *dst_resource = &dst_surface->container->resource; + struct wined3d_device *device = dst_resource->device; enum wined3d_blit_op blit_op = op; - struct wined3d_device *device; struct wined3d_blitter *next; - TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", - blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), - wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); - - src_resource = &src_texture->resource; - dst_resource = &dst_texture->resource; - - device = dst_resource->device; - if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_resource->format->id == src_resource->format->id) { if (dst_resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) @@ -2127,30 +2700,23 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit if (!fbo_blitter_supported(blit_op, context->gl_info, src_resource, src_location, dst_resource, dst_location)) { - if (!(next = blitter->next)) - { - ERR("No blitter to handle blit op %#x.\n", op); - return dst_location; - } - - TRACE("Forwarding to blitter %p.\n", next); - return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + if ((next = blitter->next)) + return next->ops->blitter_blit(next, op, context, src_surface, src_location, + src_rect, dst_surface, dst_location, dst_rect, colour_key, filter); } if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT) { TRACE("Colour blit.\n"); - texture2d_blt_fbo(device, context, filter, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect); + surface_blt_fbo(device, context, filter, src_surface, src_location, + src_rect, dst_surface, dst_location, dst_rect); return dst_location; } if (blit_op == WINED3D_BLIT_OP_DEPTH_BLIT) { TRACE("Depth/stencil blit.\n"); - texture2d_depth_blt_fbo(device, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect); + surface_depth_blt_fbo(device, src_surface, src_location, src_rect, dst_surface, dst_location, dst_rect); return dst_location; } @@ -2213,17 +2779,21 @@ static void raw_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de /* Context activation is done by the caller. */ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - 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, + struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, + const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) { const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int src_sub_resource_idx, dst_sub_resource_idx; unsigned int src_level, src_layer, dst_level, dst_layer; + struct wined3d_texture *src_texture, *dst_texture; struct wined3d_blitter *next; GLuint src_name, dst_name; DWORD location; + src_texture = src_surface->container; + dst_texture = dst_surface->container; + /* If we would need to copy from a renderbuffer or drawable, we'd probably * be better of using the FBO blitter directly, since we'd need to use it * to copy the resource contents to the texture anyway. */ @@ -2239,15 +2809,17 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit } TRACE("Forwarding to blitter %p.\n", next); - return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + return next->ops->blitter_blit(next, op, context, src_surface, src_location, + src_rect, dst_surface, dst_location, dst_rect, colour_key, filter); } TRACE("Blit using ARB_copy_image.\n"); + src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); src_level = src_sub_resource_idx % src_texture->level_count; src_layer = src_sub_resource_idx / src_texture->level_count; + dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); dst_level = dst_sub_resource_idx % dst_texture->level_count; dst_layer = dst_sub_resource_idx / dst_texture->level_count; @@ -2332,9 +2904,6 @@ static BOOL ffp_blit_supported(enum wined3d_blit_op blit_op, const struct wined3 const struct wined3d_format *dst_format = dst_resource->format; BOOL decompress; - if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) - return FALSE; - decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED); if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) @@ -2469,14 +3038,15 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de } static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - 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, + struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, + const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + struct wined3d_texture *src_texture = src_surface->container; + struct wined3d_texture *dst_texture = dst_surface->container; const struct wined3d_gl_info *gl_info = context->gl_info; struct wined3d_resource *src_resource, *dst_resource; - struct wined3d_texture *staging_texture = NULL; struct wined3d_color_key old_blt_key; struct wined3d_device *device; struct wined3d_blitter *next; @@ -2490,66 +3060,28 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit if (!ffp_blit_supported(op, context, src_resource, src_location, dst_resource, dst_location)) { if ((next = blitter->next)) - 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); + return next->ops->blitter_blit(next, op, context, src_surface, src_location, + src_rect, dst_surface, dst_location, dst_rect, color_key, filter); } - TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n", - src_texture, src_sub_resource_idx, dst_texture, dst_sub_resource_idx); + TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface); old_blt_key = src_texture->async.src_blt_color_key; old_color_key_flags = src_texture->async.color_key_flags; wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, color_key); - if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) - { - struct wined3d_resource_desc desc; - struct wined3d_box upload_box; - unsigned int src_level; - HRESULT hr; - - TRACE("Source texture is not GPU accessible, creating a staging texture.\n"); - - src_level = src_sub_resource_idx % src_texture->level_count; - desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; - desc.format = src_texture->resource.format->id; - desc.multisample_type = src_texture->resource.multisample_type; - desc.multisample_quality = src_texture->resource.multisample_quality; - desc.usage = WINED3DUSAGE_PRIVATE; - desc.access = WINED3D_RESOURCE_ACCESS_GPU; - desc.width = wined3d_texture_get_level_width(src_texture, src_level); - desc.height = wined3d_texture_get_level_height(src_texture, src_level); - desc.depth = 1; - desc.size = 0; - - if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0, - NULL, NULL, &wined3d_null_parent_ops, &staging_texture))) - { - ERR("Failed to create staging texture, hr %#x.\n", hr); - return dst_location; - } - - wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth); - wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0, - src_texture, src_sub_resource_idx, &upload_box); - - src_texture = staging_texture; - src_sub_resource_idx = 0; - } - else - { - /* Make sure the surface is up-to-date. This should probably use - * surface_load_location() and worry about the destination surface - * too, unless we're overwriting it completely. */ - wined3d_texture_load(src_texture, context, FALSE); - } + /* Make sure the surface is up-to-date. This should probably use + * surface_load_location() and worry about the destination surface too, + * unless we're overwriting it completely. */ + wined3d_texture_load(src_texture, context, FALSE); - context_apply_ffp_blit_state(context, device); + /* Activate the destination context, set it up for blitting. */ + context_apply_blit_state(context, device); if (dst_location == WINED3D_LOCATION_DRAWABLE) { r = *dst_rect; - wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &r); + surface_translate_drawable_coords(dst_surface, context->win_handle, &r); dst_rect = &r; } @@ -2559,16 +3091,15 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit if (dst_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Destination texture %p is onscreen.\n", dst_texture); + TRACE("Destination surface %p is onscreen.\n", dst_surface); buffer = wined3d_texture_get_gl_buffer(dst_texture); } else { - TRACE("Destination texture %p is offscreen.\n", dst_texture); + TRACE("Destination surface %p is offscreen.\n", dst_surface); buffer = GL_COLOR_ATTACHMENT0; } - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, - dst_resource, dst_sub_resource_idx, NULL, 0, dst_location); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location); context_set_draw_buffer(context, buffer); context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -2596,7 +3127,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit checkGLcall("glAlphaFunc"); } - context_draw_textured_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter); + draw_textured_quad(src_texture, src_sub_resource_idx, context, src_rect, dst_rect, filter); if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || color_key) { @@ -2604,6 +3135,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit checkGLcall("glDisable(GL_ALPHA_TEST)"); } + /* Leave the OpenGL state valid for blitting. */ gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) @@ -2617,16 +3149,14 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); } - if (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture) - gl_info->gl_ops.gl.p_glFlush(); + if (wined3d_settings.strict_draw_ordering + || (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture)) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ /* Restore the color key parameters */ wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL); - if (staging_texture) - wined3d_texture_decref(staging_texture); - return dst_location; } @@ -3402,13 +3932,16 @@ static void cpu_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de } static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - 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, + struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, + const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); + struct wined3d_texture *dst_texture = dst_surface->container; + struct wined3d_texture *src_texture = src_surface->container; struct wined3d_blt_fx fx; DWORD flags = 0; @@ -3462,12 +3995,17 @@ struct wined3d_blitter *wined3d_cpu_blitter_create(void) return blitter; } -HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - const struct wined3d_box *dst_box, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - const struct wined3d_box *src_box, DWORD flags, const struct wined3d_blt_fx *fx, - enum wined3d_texture_filter_type filter) +HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) { + struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; + struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; + unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); + unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource; + struct wined3d_texture *dst_texture = dst_surface->container; + struct wined3d_texture *src_texture = src_surface->container; struct wined3d_device *device = dst_texture->resource.device; struct wined3d_swapchain *src_swapchain, *dst_swapchain; const struct wined3d_color_key *colour_key = NULL; @@ -3476,17 +4014,15 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ struct wined3d_context *context; enum wined3d_blit_op blit_op; BOOL scale, convert, resolve; - RECT src_rect, dst_rect; static const DWORD simple_blit = WINED3D_BLT_SRC_CKEY | WINED3D_BLT_SRC_CKEY_OVERRIDE | WINED3D_BLT_ALPHA_TEST | WINED3D_BLT_RAW; - TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_box %s, src_texture %p, " - "src_sub_resource_idx %u, src_box %s, flags %#x, fx %p, filter %s.\n", - dst_texture, dst_sub_resource_idx, debug_box(dst_box), src_texture, src_sub_resource_idx, - debug_box(src_box), flags, fx, debug_d3dtexturefiltertype(filter)); + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), + flags, fx, debug_d3dtexturefiltertype(filter)); TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage)); if (fx) @@ -3500,9 +4036,6 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ fx->src_color_key.color_space_high_value); } - SetRect(&src_rect, src_box->left, src_box->top, src_box->right, src_box->bottom); - SetRect(&dst_rect, dst_box->left, dst_box->top, dst_box->right, dst_box->bottom); - if (!fx || !(fx->fx)) flags &= ~WINED3D_BLT_FX; @@ -3523,6 +4056,16 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ goto cpu; } + /* We want to avoid invalidating the sysmem location for converted + * surfaces, since otherwise we'd have to convert the data back when + * locking them. */ + if (dst_texture->flags & WINED3D_TEXTURE_CONVERTED || dst_texture->resource.format->conv_byte_count + || wined3d_format_get_color_key_conversion(dst_texture, TRUE)) + { + WARN_(d3d_perf)("Converted surface, using CPU blit.\n"); + goto cpu; + } + if (flags & ~simple_blit) { WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags); @@ -3543,8 +4086,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ goto fallback; } - scale = src_box->right - src_box->left != dst_box->right - dst_box->left - || src_box->bottom - src_box->top != dst_box->bottom - dst_box->top; + scale = src_rect->right - src_rect->left != dst_rect->right - dst_rect->left + || src_rect->bottom - src_rect->top != dst_rect->bottom - dst_rect->top; convert = src_texture->resource.format->id != dst_texture->resource.format->id; resolve = src_texture->resource.multisample_type != dst_texture->resource.multisample_type; @@ -3565,8 +4108,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ context = context_acquire(device, dst_texture, dst_sub_resource_idx); valid_locations = device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_DEPTH_BLIT, context, - src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter); + src_surface, src_texture->resource.draw_binding, src_rect, + dst_surface, dst_location, dst_rect, NULL, filter); context_release(context); wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations); @@ -3620,16 +4163,19 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ TRACE("Not doing upload because the destination format needs conversion.\n"); else { - wined3d_texture_upload_from_texture(dst_texture, dst_sub_resource_idx, dst_box->left, - dst_box->top, dst_box->front, src_texture, src_sub_resource_idx, src_box); - if (!wined3d_resource_is_offscreen(&dst_texture->resource)) + POINT dst_point = {dst_rect->left, dst_rect->top}; + + if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, src_rect))) { - context = context_acquire(device, dst_texture, dst_sub_resource_idx); - wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, - context, dst_texture->resource.draw_binding); - context_release(context); + if (!wined3d_resource_is_offscreen(&dst_texture->resource)) + { + context = context_acquire(device, dst_texture, dst_sub_resource_idx); + wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, + context, dst_texture->resource.draw_binding); + context_release(context); + } + return WINED3D_OK; } - return WINED3D_OK; } } else if (dst_swapchain && dst_swapchain->back_buffers @@ -3649,8 +4195,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ /* Set the swap effect to COPY, we don't want the backbuffer to become * undefined. */ dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; - wined3d_swapchain_present(dst_swapchain, NULL, NULL, - dst_swapchain->win_handle, dst_swapchain->swap_interval, 0); + wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0, 0); dst_swapchain->desc.swap_effect = swap_effect; return WINED3D_OK; @@ -3667,8 +4212,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ context = context_acquire(device, dst_texture, dst_sub_resource_idx); valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context, - src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter); + src_surface, src_texture->resource.draw_binding, src_rect, + dst_surface, dst_location, dst_rect, colour_key, filter); context_release(context); wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations); @@ -3678,11 +4223,10 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ fallback: /* Special cases for render targets. */ - if (SUCCEEDED(wined3d_texture_blt_special(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, flags, fx, filter))) + if (SUCCEEDED(surface_blt_special(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter))) return WINED3D_OK; cpu: - return surface_cpu_blt(dst_texture, dst_sub_resource_idx, dst_box, - src_texture, src_sub_resource_idx, src_box, flags, fx, filter); + return surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box, + src_texture, src_sub_resource_idx, &src_box, flags, fx, filter); } diff --git a/dll/directx/wine/wined3d/swapchain.c b/dll/directx/wine/wined3d/swapchain.c index 7fee86692e0..8c67a0d42be 100644 --- a/dll/directx/wine/wined3d/swapchain.c +++ b/dll/directx/wine/wined3d/swapchain.c @@ -151,20 +151,24 @@ void CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWN HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, - unsigned int swap_interval, DWORD flags) + DWORD swap_interval, DWORD flags) { + static DWORD notified_flags = 0; RECT s, d; TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, flags %#x.\n", swapchain, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, flags); - if (flags) - FIXME("Ignoring flags %#x.\n", flags); + if (flags & ~notified_flags) + { + FIXME("Ignoring flags %#x.\n", flags & ~notified_flags); + notified_flags |= flags; + } if (!swapchain->back_buffers) { - WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL.\n"); + WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n"); return WINED3DERR_INVALIDCALL; } @@ -314,6 +318,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect) { struct wined3d_texture *texture = swapchain->back_buffers[0]; + struct wined3d_surface *back_buffer = texture->sub_resources[0].u.surface; struct wined3d_device *device = swapchain->device; enum wined3d_texture_filter_type filter; DWORD location; @@ -333,8 +338,8 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, location = WINED3D_LOCATION_RB_RESOLVED; wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); - device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, 0, - location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter); + device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, back_buffer, + location, src_rect, back_buffer, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter); wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); } @@ -390,7 +395,6 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, { struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; const struct wined3d_fb_state *fb = &swapchain->device->cs->fb; - struct wined3d_rendertarget_view *dsv = fb->depth_stencil; const struct wined3d_gl_info *gl_info; struct wined3d_texture *logo_texture; struct wined3d_context *context; @@ -476,7 +480,11 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, if (swapchain->render_to_fbo) swapchain_blit(swapchain, context, src_rect, dst_rect); +#if !defined(STAGING_CSMT) if (swapchain->num_contexts > 1) +#else /* STAGING_CSMT */ + if (swapchain->num_contexts > 1 && !wined3d_settings.cs_multithreaded) +#endif /* STAGING_CSMT */ gl_info->gl_ops.gl.p_glFinish(); /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ @@ -515,13 +523,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, wined3d_texture_validate_location(swapchain->back_buffers[swapchain->desc.backbuffer_count - 1], 0, WINED3D_LOCATION_DISCARDED); - if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER) + if (fb->depth_stencil) { - struct wined3d_texture *ds = texture_from_resource(dsv->resource); + struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(fb->depth_stencil); - if ((swapchain->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL - || ds->flags & WINED3D_TEXTURE_DISCARD)) - wined3d_texture_validate_location(ds, dsv->sub_resource_idx, WINED3D_LOCATION_DISCARDED); + if (ds && (swapchain->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL + || ds->container->flags & WINED3D_TEXTURE_DISCARD)) + wined3d_texture_validate_location(ds->container, + fb->depth_stencil->sub_resource_idx, WINED3D_LOCATION_DISCARDED); } context_release(context); @@ -546,7 +555,7 @@ static const struct wined3d_swapchain_ops swapchain_gl_ops = static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchain) { - struct wined3d_dc_info *front; + struct wined3d_surface *front; POINT offset = {0, 0}; HDC src_dc, dst_dc; RECT draw_rect; @@ -554,11 +563,11 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai TRACE("swapchain %p.\n", swapchain); - front = &swapchain->front_buffer->dc_info[0]; + front = swapchain->front_buffer->sub_resources[0].u.surface; if (swapchain->palette) wined3d_palette_apply_to_dc(swapchain->palette, front->dc); - if (swapchain->front_buffer->resource.map_count) + if (front->container->resource.map_count) ERR("Trying to blit a mapped surface.\n"); TRACE("Copying surface %p to screen.\n", front); @@ -589,26 +598,26 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, DWORD flags) { - struct wined3d_dc_info *front, *back; + struct wined3d_surface *front, *back; HBITMAP bitmap; void *data; HDC dc; - front = &swapchain->front_buffer->dc_info[0]; - back = &swapchain->back_buffers[0]->dc_info[0]; + front = swapchain->front_buffer->sub_resources[0].u.surface; + back = swapchain->back_buffers[0]->sub_resources[0].u.surface; /* Flip the surface data. */ dc = front->dc; bitmap = front->bitmap; - data = swapchain->front_buffer->resource.heap_memory; + data = front->container->resource.heap_memory; front->dc = back->dc; front->bitmap = back->bitmap; - swapchain->front_buffer->resource.heap_memory = swapchain->back_buffers[0]->resource.heap_memory; + front->container->resource.heap_memory = back->container->resource.heap_memory; back->dc = dc; back->bitmap = bitmap; - swapchain->back_buffers[0]->resource.heap_memory = data; + back->container->resource.heap_memory = data; /* FPS support */ if (TRACE_ON(fps)) @@ -677,26 +686,44 @@ static void wined3d_swapchain_apply_sample_count_override(const struct wined3d_s *quality = 0; } -void wined3d_swapchain_set_swap_interval(struct wined3d_swapchain *swapchain, - unsigned int swap_interval) +static void wined3d_swapchain_update_swap_interval_cs(void *object) { + struct wined3d_swapchain *swapchain = object; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; - - swap_interval = swap_interval <= 4 ? swap_interval : 1; - if (swapchain->swap_interval == swap_interval) - return; - - swapchain->swap_interval = swap_interval; + int swap_interval; context = context_acquire(swapchain->device, swapchain->front_buffer, 0); gl_info = context->gl_info; + switch (swapchain->desc.swap_interval) + { + case WINED3DPRESENT_INTERVAL_IMMEDIATE: + swap_interval = 0; + break; + case WINED3DPRESENT_INTERVAL_DEFAULT: + case WINED3DPRESENT_INTERVAL_ONE: + swap_interval = 1; + break; + case WINED3DPRESENT_INTERVAL_TWO: + swap_interval = 2; + break; + case WINED3DPRESENT_INTERVAL_THREE: + swap_interval = 3; + break; + case WINED3DPRESENT_INTERVAL_FOUR: + swap_interval = 4; + break; + default: + FIXME("Unhandled present interval %#x.\n", swapchain->desc.swap_interval); + swap_interval = 1; + } + if (gl_info->supported[WGL_EXT_SWAP_CONTROL]) { if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval))) - ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x.\n", - swap_interval, context, GetLastError()); + ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x\n", + swap_interval, context, GetLastError()); } context_release(context); @@ -742,12 +769,8 @@ static void wined3d_swapchain_cs_init(void *object) FIXME("Add OpenGL context recreation support.\n"); context_release(swapchain->context[0]); -} -void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, const struct wined3d_device *device) -{ - /* Subtract 1 for the implicit OpenGL latency. */ - swapchain->max_frame_latency = device->max_frame_latency >= 2 ? device->max_frame_latency - 1 : 1; + wined3d_swapchain_update_swap_interval_cs(swapchain); } static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, @@ -758,9 +781,9 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 BOOL displaymode_set = FALSE; DWORD texture_flags = 0; RECT client_rect; - unsigned int i; HWND window; HRESULT hr; + UINT i; if (desc->backbuffer_count > 1) { @@ -786,8 +809,6 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 swapchain->ref = 1; swapchain->win_handle = window; swapchain->device_window = window; - swapchain->swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT; - swapchain_set_max_frame_latency(swapchain, device); if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, adapter->ordinal, &swapchain->original_mode, NULL))) @@ -800,16 +821,15 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 GetClientRect(window, &client_rect); if (desc->windowed) { - TRACE("Client rect %s.\n", wine_dbgstr_rect(&client_rect)); - if (!desc->backbuffer_width) { - desc->backbuffer_width = client_rect.right ? client_rect.right : 8; + desc->backbuffer_width = client_rect.right; TRACE("Updating width to %u.\n", desc->backbuffer_width); } + if (!desc->backbuffer_height) { - desc->backbuffer_height = client_rect.bottom ? client_rect.bottom : 8; + desc->backbuffer_height = client_rect.bottom; TRACE("Updating height to %u.\n", desc->backbuffer_height); } @@ -1121,6 +1141,11 @@ void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) } } +void swapchain_update_swap_interval(struct wined3d_swapchain *swapchain) +{ + wined3d_cs_init_object(swapchain->device->cs, wined3d_swapchain_update_swap_interval_cs, swapchain); +} + void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate) { struct wined3d_device *device = swapchain->device; diff --git a/dll/directx/wine/wined3d/texture.c b/dll/directx/wine/wined3d/texture.c index bee7f35e2bc..e6af0c75088 100644 --- a/dll/directx/wine/wined3d/texture.c +++ b/dll/directx/wine/wined3d/texture.c @@ -30,20 +30,6 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); #define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50 -struct wined3d_texture_idx -{ - struct wined3d_texture *texture; - unsigned int sub_resource_idx; -}; - -struct wined3d_rect_f -{ - float l; - float t; - float r; - float b; -}; - static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) { return !(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) @@ -62,32 +48,6 @@ static BOOL wined3d_texture_use_immutable_storage(const struct wined3d_texture * && !(texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE); } -/* Front buffer coordinates are always full screen coordinates, but our GL - * drawable is limited to the window's client area. The sysmem and texture - * copies do have the full screen size. Note that GL has a bottom-left - * origin, while D3D has a top-left origin. */ -void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect) -{ - unsigned int drawable_height; - POINT offset = {0, 0}; - RECT windowsize; - - if (!texture->swapchain) - return; - - if (texture == texture->swapchain->front_buffer) - { - ScreenToClient(window, &offset); - OffsetRect(rect, offset.x, offset.y); - } - - GetClientRect(window, &windowsize); - drawable_height = windowsize.bottom - windowsize.top; - - rect->top = drawable_height - rect->top; - rect->bottom = drawable_height - rect->bottom; -} - GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) { const struct wined3d_swapchain *swapchain = texture->swapchain; @@ -141,120 +101,9 @@ static DWORD wined3d_resource_access_from_location(DWORD location) } } -static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct wined3d_rect_f *f) -{ - f->l = ((r->left * 2.0f) / w) - 1.0f; - f->t = ((r->top * 2.0f) / h) - 1.0f; - f->r = ((r->right * 2.0f) / w) - 1.0f; - f->b = ((r->bottom * 2.0f) / h) - 1.0f; -} - -void texture2d_get_blt_info(const struct wined3d_texture *texture, - unsigned int sub_resource_idx, const RECT *rect, struct wined3d_blt_info *info) +static BOOL is_power_of_two(UINT x) { - struct wined3d_vec3 *coords = info->texcoords; - struct wined3d_rect_f f; - unsigned int level; - GLenum target; - GLsizei w, h; - - level = sub_resource_idx % texture->level_count; - w = wined3d_texture_get_level_pow2_width(texture, level); - h = wined3d_texture_get_level_pow2_height(texture, level); - target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); - - switch (target) - { - default: - FIXME("Unsupported texture target %#x.\n", target); - /* Fall back to GL_TEXTURE_2D */ - case GL_TEXTURE_2D: - info->bind_target = GL_TEXTURE_2D; - coords[0].x = (float)rect->left / w; - coords[0].y = (float)rect->top / h; - coords[0].z = 0.0f; - - coords[1].x = (float)rect->right / w; - coords[1].y = (float)rect->top / h; - coords[1].z = 0.0f; - - coords[2].x = (float)rect->left / w; - coords[2].y = (float)rect->bottom / h; - coords[2].z = 0.0f; - - coords[3].x = (float)rect->right / w; - coords[3].y = (float)rect->bottom / h; - coords[3].z = 0.0f; - break; - - case GL_TEXTURE_RECTANGLE_ARB: - info->bind_target = GL_TEXTURE_RECTANGLE_ARB; - coords[0].x = rect->left; coords[0].y = rect->top; coords[0].z = 0.0f; - coords[1].x = rect->right; coords[1].y = rect->top; coords[1].z = 0.0f; - coords[2].x = rect->left; coords[2].y = rect->bottom; coords[2].z = 0.0f; - coords[3].x = rect->right; coords[3].y = rect->bottom; coords[3].z = 0.0f; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = 1.0f; coords[0].y = -f.t; coords[0].z = -f.l; - coords[1].x = 1.0f; coords[1].y = -f.t; coords[1].z = -f.r; - coords[2].x = 1.0f; coords[2].y = -f.b; coords[2].z = -f.l; - coords[3].x = 1.0f; coords[3].y = -f.b; coords[3].z = -f.r; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = -1.0f; coords[0].y = -f.t; coords[0].z = f.l; - coords[1].x = -1.0f; coords[1].y = -f.t; coords[1].z = f.r; - coords[2].x = -1.0f; coords[2].y = -f.b; coords[2].z = f.l; - coords[3].x = -1.0f; coords[3].y = -f.b; coords[3].z = f.r; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = f.l; coords[0].y = 1.0f; coords[0].z = f.t; - coords[1].x = f.r; coords[1].y = 1.0f; coords[1].z = f.t; - coords[2].x = f.l; coords[2].y = 1.0f; coords[2].z = f.b; - coords[3].x = f.r; coords[3].y = 1.0f; coords[3].z = f.b; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = f.l; coords[0].y = -1.0f; coords[0].z = -f.t; - coords[1].x = f.r; coords[1].y = -1.0f; coords[1].z = -f.t; - coords[2].x = f.l; coords[2].y = -1.0f; coords[2].z = -f.b; - coords[3].x = f.r; coords[3].y = -1.0f; coords[3].z = -f.b; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = f.l; coords[0].y = -f.t; coords[0].z = 1.0f; - coords[1].x = f.r; coords[1].y = -f.t; coords[1].z = 1.0f; - coords[2].x = f.l; coords[2].y = -f.b; coords[2].z = 1.0f; - coords[3].x = f.r; coords[3].y = -f.b; coords[3].z = 1.0f; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - info->bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(rect, w, h, &f); - - coords[0].x = -f.l; coords[0].y = -f.t; coords[0].z = -1.0f; - coords[1].x = -f.r; coords[1].y = -f.t; coords[1].z = -1.0f; - coords[2].x = -f.l; coords[2].y = -f.b; coords[2].z = -1.0f; - coords[3].x = -f.r; coords[3].y = -f.b; coords[3].z = -1.0f; - break; - } + return (x != 0) && !(x & (x - 1)); } static void wined3d_texture_evict_sysmem(struct wined3d_texture *texture) @@ -445,7 +294,11 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su if (locations & WINED3D_LOCATION_BUFFER) { data->addr = NULL; +#if !defined(STAGING_CSMT) data->buffer_object = sub_resource->buffer_object; +#else /* STAGING_CSMT */ + data->buffer_object = sub_resource->buffer->name; +#endif /* STAGING_CSMT */ return; } if (locations & WINED3D_LOCATION_USER_MEMORY) @@ -467,8 +320,93 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su data->buffer_object = 0; } +static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops, + UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, DWORD flags, + struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops, + const struct wined3d_resource_ops *resource_ops) +{ + unsigned int i, j, size, offset = 0; + const struct wined3d_format *format; + HRESULT hr; + + TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, " + "multisample_type %#x, multisample_quality %#x, usage %s, access %s, width %u, height %u, depth %u, " + "flags %#x, device %p, parent %p, parent_ops %p, resource_ops %p.\n", + texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type), + debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality, + debug_d3dusage(desc->usage), wined3d_debug_resource_access(desc->access), + desc->width, desc->height, desc->depth, flags, device, parent, parent_ops, resource_ops); + + if (!desc->width || !desc->height || !desc->depth) + return WINED3DERR_INVALIDCALL; + + format = wined3d_get_format(&device->adapter->gl_info, desc->format, desc->usage); + + for (i = 0; i < layer_count; ++i) + { + for (j = 0; j < level_count; ++j) + { + unsigned int idx = i * level_count + j; + + size = wined3d_format_calculate_size(format, device->surface_alignment, + max(1, desc->width >> j), max(1, desc->height >> j), max(1, desc->depth >> j)); + texture->sub_resources[idx].offset = offset; + texture->sub_resources[idx].size = size; + offset += size; + } + offset = (offset + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1); + } + + if (!offset) + return WINED3DERR_INVALIDCALL; + + if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format, + desc->multisample_type, desc->multisample_quality, desc->usage, desc->access, + desc->width, desc->height, desc->depth, offset, parent, parent_ops, resource_ops))) + { + static unsigned int once; + + /* DXTn 3D textures are not supported. Do not write the ERR for them. */ + if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3 + || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5) + && !(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE) + && desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !once++) + ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n"); + + WARN("Failed to initialize resource, returning %#x\n", hr); + return hr; + } + wined3d_resource_update_draw_binding(&texture->resource); + if ((flags & WINED3D_TEXTURE_CREATE_MAPPABLE) || desc->format == WINED3DFMT_D16_LOCKABLE) + texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; + + texture->texture_ops = texture_ops; + + texture->layer_count = layer_count; + texture->level_count = level_count; + texture->lod = 0; + texture->flags |= WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS; + if (flags & WINED3D_TEXTURE_CREATE_GET_DC_LENIENT) + texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_GET_DC_LENIENT; + if (flags & (WINED3D_TEXTURE_CREATE_GET_DC | WINED3D_TEXTURE_CREATE_GET_DC_LENIENT)) + texture->flags |= WINED3D_TEXTURE_GET_DC; + if (flags & WINED3D_TEXTURE_CREATE_DISCARD) + texture->flags |= WINED3D_TEXTURE_DISCARD; + if (flags & WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS) + { + if (!(texture->resource.format_flags & WINED3DFMT_FLAG_GEN_MIPMAP)) + WARN("Format doesn't support mipmaps generation, " + "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n"); + else + texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS; + } + + return WINED3D_OK; +} + /* Context activation is done by the caller. */ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture, +#if !defined(STAGING_CSMT) unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) { GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; @@ -481,6 +419,19 @@ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); *buffer_object = 0; +#else /* STAGING_CSMT */ + unsigned int sub_resource_idx, struct wined3d_context *context) +{ + struct wined3d_gl_bo *buffer = texture->sub_resources[sub_resource_idx].buffer; + GLuint name = buffer->name; + + wined3d_device_release_bo(texture->resource.device, buffer, context); + texture->sub_resources[sub_resource_idx].buffer = NULL; + wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + + TRACE("Deleted buffer object %u for texture %p, sub-resource %u.\n", + name, texture, sub_resource_idx); +#endif /* STAGING_CSMT */ } static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) @@ -500,7 +451,11 @@ static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) && !wined3d_texture_load_location(texture, i, context, map_binding)) ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding)); if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER) +#if !defined(STAGING_CSMT) wined3d_texture_remove_buffer_object(texture, i, context->gl_info); +#else /* STAGING_CSMT */ + wined3d_texture_remove_buffer_object(texture, i, context); +#endif /* STAGING_CSMT */ } if (context) @@ -565,14 +520,11 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture * const struct wined3d_gl_info *gl_info) { unsigned int level, level_count, layer, layer_count; - GLsizei width, height, depth; + GLsizei width, height; GLenum target; level_count = texture->level_count; - if (texture->target == GL_TEXTURE_1D_ARRAY || texture->target == GL_TEXTURE_2D_ARRAY) - layer_count = 1; - else - layer_count = texture->layer_count; + layer_count = texture->target == GL_TEXTURE_2D_ARRAY ? 1 : texture->layer_count; for (layer = 0; layer < layer_count; ++layer) { @@ -591,24 +543,16 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture * TRACE("texture %p, layer %u, level %u, target %#x, width %u, height %u.\n", texture, layer, level, target, width, height); - if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY) + if (texture->target == GL_TEXTURE_2D_ARRAY) { - depth = wined3d_texture_get_level_depth(texture, level); GL_EXTCALL(glTexImage3D(target, level, gl_internal_format, width, height, - target == GL_TEXTURE_2D_ARRAY ? texture->layer_count : depth, 0, - format->glFormat, format->glType, NULL)); + texture->layer_count, 0, format->glFormat, format->glType, NULL)); checkGLcall("glTexImage3D"); } - else if (target == GL_TEXTURE_1D) - { - gl_info->gl_ops.gl.p_glTexImage1D(target, level, gl_internal_format, - width, 0, format->glFormat, format->glType, NULL); - } else { - gl_info->gl_ops.gl.p_glTexImage2D(target, level, gl_internal_format, width, - target == GL_TEXTURE_1D_ARRAY ? texture->layer_count : height, 0, - format->glFormat, format->glType, NULL); + gl_info->gl_ops.gl.p_glTexImage2D(target, level, gl_internal_format, + width, height, 0, format->glFormat, format->glType, NULL); checkGLcall("glTexImage2D"); } } @@ -626,10 +570,6 @@ static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture switch (texture->target) { - case GL_TEXTURE_3D: - GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count, - gl_internal_format, width, height, wined3d_texture_get_level_depth(texture, 0))); - break; case GL_TEXTURE_2D_ARRAY: GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count, gl_internal_format, width, height, texture->layer_count)); @@ -642,13 +582,6 @@ static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture GL_EXTCALL(glTexStorage3DMultisample(texture->target, samples, gl_internal_format, width, height, texture->layer_count, GL_FALSE)); break; - case GL_TEXTURE_1D_ARRAY: - GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count, - gl_internal_format, width, texture->layer_count)); - break; - case GL_TEXTURE_1D: - GL_EXTCALL(glTexStorage1D(texture->target, texture->level_count, gl_internal_format, width)); - break; default: GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count, gl_internal_format, width, height)); @@ -718,185 +651,56 @@ static void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *text } } -static void wined3d_texture_create_dc(void *object) -{ - const struct wined3d_texture_idx *idx = object; - struct wined3d_context *context = NULL; - unsigned int sub_resource_idx, level; - const struct wined3d_format *format; - unsigned int row_pitch, slice_pitch; - struct wined3d_texture *texture; - struct wined3d_dc_info *dc_info; - struct wined3d_bo_address data; - D3DKMT_CREATEDCFROMMEMORY desc; - struct wined3d_device *device; - NTSTATUS status; - - TRACE("texture %p, sub_resource_idx %u.\n", idx->texture, idx->sub_resource_idx); - - texture = idx->texture; - sub_resource_idx = idx->sub_resource_idx; - level = sub_resource_idx % texture->level_count; - device = texture->resource.device; - - format = texture->resource.format; - if (!format->ddi_format) - { - WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id)); - return; - } - - if (!texture->dc_info) - { - unsigned int sub_count = texture->level_count * texture->layer_count; - - if (!(texture->dc_info = heap_calloc(sub_count, sizeof(*texture->dc_info)))) - { - ERR("Failed to allocate DC info.\n"); - return; - } - } - - if (device->d3d_initialized) - context = context_acquire(device, NULL, 0); - - wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); - wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); - wined3d_texture_get_pitch(texture, level, &row_pitch, &slice_pitch); - wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - desc.pMemory = context_map_bo_address(context, &data, - texture->sub_resources[sub_resource_idx].size, - GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE); - - if (context) - context_release(context); - - desc.Format = format->ddi_format; - desc.Width = wined3d_texture_get_level_width(texture, level); - desc.Height = wined3d_texture_get_level_height(texture, level); - desc.Pitch = row_pitch; - desc.hDeviceDc = CreateCompatibleDC(NULL); - desc.pColorTable = NULL; - - status = D3DKMTCreateDCFromMemory(&desc); - DeleteDC(desc.hDeviceDc); - if (status) - { - WARN("Failed to create DC, status %#x.\n", status); - return; - } - - dc_info = &texture->dc_info[sub_resource_idx]; - dc_info->dc = desc.hDc; - dc_info->bitmap = desc.hBitmap; - - TRACE("Created DC %p, bitmap %p for texture %p, %u.\n", dc_info->dc, dc_info->bitmap, texture, sub_resource_idx); -} - -static void wined3d_texture_destroy_dc(void *object) -{ - const struct wined3d_texture_idx *idx = object; - D3DKMT_DESTROYDCFROMMEMORY destroy_desc; - struct wined3d_context *context = NULL; - struct wined3d_texture *texture; - struct wined3d_dc_info *dc_info; - struct wined3d_bo_address data; - unsigned int sub_resource_idx; - struct wined3d_device *device; - NTSTATUS status; - - texture = idx->texture; - sub_resource_idx = idx->sub_resource_idx; - device = texture->resource.device; - dc_info = &texture->dc_info[sub_resource_idx]; - - if (!dc_info->dc) - { - ERR("Sub-resource {%p, %u} has no DC.\n", texture, sub_resource_idx); - return; - } - - TRACE("dc %p, bitmap %p.\n", dc_info->dc, dc_info->bitmap); - - destroy_desc.hDc = dc_info->dc; - destroy_desc.hBitmap = dc_info->bitmap; - if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc))) - ERR("Failed to destroy dc, status %#x.\n", status); - dc_info->dc = NULL; - dc_info->bitmap = NULL; - - if (device->d3d_initialized) - context = context_acquire(device, NULL, 0); - - wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER); - - if (context) - context_release(context); -} - static void wined3d_texture_cleanup(struct wined3d_texture *texture) { unsigned int sub_count = texture->level_count * texture->layer_count; struct wined3d_device *device = texture->resource.device; - struct wined3d_renderbuffer_entry *entry, *entry2; - const struct wined3d_gl_info *gl_info = NULL; struct wined3d_context *context = NULL; - struct wined3d_dc_info *dc_info; +#if !defined(STAGING_CSMT) + const struct wined3d_gl_info *gl_info; GLuint buffer_object; +#else /* STAGING_CSMT */ + struct wined3d_gl_bo *buffer; +#endif /* STAGING_CSMT */ unsigned int i; TRACE("texture %p.\n", texture); for (i = 0; i < sub_count; ++i) { +#if !defined(STAGING_CSMT) if (!(buffer_object = texture->sub_resources[i].buffer_object)) continue; TRACE("Deleting buffer object %u.\n", buffer_object); +#else /* STAGING_CSMT */ + if (!(buffer = texture->sub_resources[i].buffer)) + continue; + + TRACE("Deleting buffer object %u.\n", buffer->name); +#endif /* STAGING_CSMT */ /* We may not be able to get a context in wined3d_texture_cleanup() in * general, but if a buffer object was previously created we can. */ if (!context) +#if !defined(STAGING_CSMT) { context = context_acquire(device, NULL, 0); gl_info = context->gl_info; } GL_EXTCALL(glDeleteBuffers(1, &buffer_object)); - } - - if (!context && !list_empty(&texture->renderbuffers)) - { - context = context_acquire(device, NULL, 0); - gl_info = context->gl_info; - } +#else /* STAGING_CSMT */ + context = context_acquire(device, NULL, 0); - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry) - { - TRACE("Deleting renderbuffer %u.\n", entry->id); - context_gl_resource_released(device, entry->id, TRUE); - gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id); - heap_free(entry); + wined3d_device_release_bo(device, buffer, context); + texture->sub_resources[i].buffer = NULL; +#endif /* STAGING_CSMT */ } - if (context) context_release(context); - if ((dc_info = texture->dc_info)) - { - for (i = 0; i < sub_count; ++i) - { - if (dc_info[i].dc) - { - struct wined3d_texture_idx texture_idx = {texture, i}; - - wined3d_texture_destroy_dc(&texture_idx); - } - } - heap_free(dc_info); - } - + texture->texture_ops->texture_cleanup_sub_resources(texture); if (texture->overlay_info) { for (i = 0; i < sub_count; ++i) @@ -1448,87 +1252,105 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture, return WINED3D_OK; } -/* In D3D the depth stencil dimensions have to be greater than or equal to the - * render target dimensions. With FBOs, the dimensions have to be an exact match. */ -/* TODO: We should synchronize the renderbuffer's content with the texture's content. */ -/* Context activation is done by the caller. */ -void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture, - unsigned int level, const struct wined3d_rendertarget_info *rt) +static void texture2d_create_dc(void *object) { - struct wined3d_renderbuffer_entry *entry; - const struct wined3d_gl_info *gl_info; - unsigned int src_width, src_height; - unsigned int width, height; - GLuint renderbuffer = 0; + struct wined3d_surface *surface = object; + struct wined3d_context *context = NULL; + const struct wined3d_format *format; + unsigned int row_pitch, slice_pitch; + struct wined3d_texture *texture; + struct wined3d_bo_address data; + D3DKMT_CREATEDCFROMMEMORY desc; + unsigned int sub_resource_idx; + struct wined3d_device *device; + NTSTATUS status; - gl_info = &texture->resource.device->adapter->gl_info; - if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]) - return; + TRACE("surface %p.\n", surface); - if (rt && rt->resource->format->id != WINED3DFMT_NULL) - { - struct wined3d_texture *rt_texture; - unsigned int rt_level; + texture = surface->container; + sub_resource_idx = surface_get_sub_resource_idx(surface); + device = texture->resource.device; - if (rt->resource->type == WINED3D_RTYPE_BUFFER) - { - FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type)); - return; - } - rt_texture = wined3d_texture_from_resource(rt->resource); - rt_level = rt->sub_resource_idx % rt_texture->level_count; - - width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level); - height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level); - } - else + format = texture->resource.format; + if (!format->ddi_format) { - width = wined3d_texture_get_level_pow2_width(texture, level); - height = wined3d_texture_get_level_pow2_height(texture, level); + WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id)); + return; } - src_width = wined3d_texture_get_level_pow2_width(texture, level); - src_height = wined3d_texture_get_level_pow2_height(texture, level); + if (device->d3d_initialized) + context = context_acquire(device, NULL, 0); - /* A depth stencil smaller than the render target is not valid */ - if (width > src_width || height > src_height) - return; + wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); + wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch); + wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); + desc.pMemory = context_map_bo_address(context, &data, + texture->sub_resources[sub_resource_idx].size, + GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE); + + if (context) + context_release(context); + + desc.Format = format->ddi_format; + desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level); + desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level); + desc.Pitch = row_pitch; + desc.hDeviceDc = CreateCompatibleDC(NULL); + desc.pColorTable = NULL; - /* Remove any renderbuffer set if the sizes match */ - if (width == src_width && height == src_height) + status = D3DKMTCreateDCFromMemory(&desc); + DeleteDC(desc.hDeviceDc); + if (status) { - texture->current_renderbuffer = NULL; + WARN("Failed to create DC, status %#x.\n", status); return; } - /* Look if we've already got a renderbuffer of the correct dimensions */ - LIST_FOR_EACH_ENTRY(entry, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry) + surface->dc = desc.hDc; + surface->bitmap = desc.hBitmap; + + TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface); +} + +static void texture2d_destroy_dc(void *object) +{ + struct wined3d_surface *surface = object; + D3DKMT_DESTROYDCFROMMEMORY destroy_desc; + struct wined3d_context *context = NULL; + struct wined3d_texture *texture; + struct wined3d_bo_address data; + unsigned int sub_resource_idx; + struct wined3d_device *device; + NTSTATUS status; + + texture = surface->container; + sub_resource_idx = surface_get_sub_resource_idx(surface); + device = texture->resource.device; + + if (!surface->dc) { - if (entry->width == width && entry->height == height) - { - renderbuffer = entry->id; - texture->current_renderbuffer = entry; - break; - } + ERR("Surface %p has no DC.\n", surface); + return; } - if (!renderbuffer) - { - gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer); - gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); - gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, - texture->resource.format->glInternal, width, height); + TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap); - entry = heap_alloc(sizeof(*entry)); - entry->width = width; - entry->height = height; - entry->id = renderbuffer; - list_add_head(&texture->renderbuffers, &entry->entry); + destroy_desc.hDc = surface->dc; + destroy_desc.hBitmap = surface->bitmap; + if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc))) + ERR("Failed to destroy dc, status %#x.\n", status); + surface->dc = NULL; + surface->bitmap = NULL; - texture->current_renderbuffer = entry; - } + if (device->d3d_initialized) + context = context_acquire(device, NULL, 0); - checkGLcall("set_compatible_renderbuffer"); + wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); + context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER); + + if (context) + context_release(context); } HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height, @@ -1540,6 +1362,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT const struct wined3d_format *format = wined3d_get_format(gl_info, format_id, texture->resource.usage); UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1); struct wined3d_texture_sub_resource *sub_resource; + struct wined3d_surface *surface; DWORD valid_location = 0; BOOL create_dib = FALSE; @@ -1562,6 +1385,12 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT return WINED3DERR_INVALIDCALL; } + if (texture->resource.type == WINED3D_RTYPE_TEXTURE_1D) + { + FIXME("Not yet supported for 1D textures.\n"); + return WINED3DERR_INVALIDCALL; + } + if (texture->resource.map_count) { WARN("Texture is mapped.\n"); @@ -1586,11 +1415,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT wined3d_resource_wait_idle(&texture->resource); sub_resource = &texture->sub_resources[0]; - if (texture->dc_info && texture->dc_info[0].dc) + surface = sub_resource->u.surface; + if (surface->dc) { - struct wined3d_texture_idx texture_idx = {texture, 0}; - - wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx); + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); create_dib = TRUE; } @@ -1618,7 +1446,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT else texture->target = GL_TEXTURE_2D; - if (((width & (width - 1)) || (height & (height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] + if ((!is_power_of_two(width) || !is_power_of_two(height)) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && !gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]) { texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED; @@ -1658,9 +1486,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT if (create_dib) { - struct wined3d_texture_idx texture_idx = {texture, 0}; - - wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx); + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -1669,11 +1495,16 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT /* Context activation is done by the caller. */ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture, +#if !defined(STAGING_CSMT) unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) +#else /* STAGING_CSMT */ + unsigned int sub_resource_idx, struct wined3d_context *context) +#endif /* STAGING_CSMT */ { struct wined3d_texture_sub_resource *sub_resource; sub_resource = &texture->sub_resources[sub_resource_idx]; +#if !defined(STAGING_CSMT) if (sub_resource->buffer_object) return; @@ -1685,6 +1516,16 @@ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *textur TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", sub_resource->buffer_object, texture, sub_resource_idx); +#else /* STAGING_CSMT */ + if (sub_resource->buffer) + return; + + sub_resource->buffer = wined3d_device_get_bo(texture->resource.device, + sub_resource->size, GL_STREAM_DRAW, GL_PIXEL_UNPACK_BUFFER, context); + + TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", + sub_resource->buffer->name, texture, sub_resource_idx); +#endif /* STAGING_CSMT */ } static void wined3d_texture_force_reload(struct wined3d_texture *texture) @@ -1702,17 +1543,10 @@ static void wined3d_texture_force_reload(struct wined3d_texture *texture) } } -/* Context activation is done by the caller. */ void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) { DWORD alloc_flag = srgb ? WINED3D_TEXTURE_SRGB_ALLOCATED : WINED3D_TEXTURE_RGB_ALLOCATED; - const struct wined3d_format *format = texture->resource.format; const struct wined3d_d3d_info *d3d_info = context->d3d_info; - const struct wined3d_gl_info *gl_info = context->gl_info; - const struct wined3d_color_key_conversion *conversion; - GLenum internal; - - TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id)); if (!d3d_info->shader_color_key && !(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY) @@ -1727,36 +1561,7 @@ void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct win if (texture->flags & alloc_flag) return; - if (format->conv_byte_count) - { - texture->flags |= WINED3D_TEXTURE_CONVERTED; - } - else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE))) - { - texture->flags |= WINED3D_TEXTURE_CONVERTED; - format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage); - TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format->id)); - } - - wined3d_texture_bind_and_dirtify(texture, context, srgb); - - if (srgb) - internal = format->glGammaInternal; - else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET - && wined3d_resource_is_offscreen(&texture->resource)) - internal = format->rtInternal; - else - internal = format->glInternal; - - if (!internal) - FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id)); - - TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType); - - if (wined3d_texture_use_immutable_storage(texture, gl_info)) - wined3d_texture_allocate_gl_immutable_storage(texture, internal, gl_info); - else - wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info); + texture->texture_ops->texture_prepare_texture(texture, context, srgb); texture->flags |= alloc_flag; } @@ -1807,7 +1612,10 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned return TRUE; if (!wined3d_resource_allocate_sysmem(&texture->resource)) + { + ERR("Failed to allocate system memory.\n"); return FALSE; + } return TRUE; case WINED3D_LOCATION_USER_MEMORY: @@ -1816,7 +1624,11 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned return TRUE; case WINED3D_LOCATION_BUFFER: +#if !defined(STAGING_CSMT) wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context->gl_info); +#else /* STAGING_CSMT */ + wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context); +#endif /* STAGING_CSMT */ return TRUE; case WINED3D_LOCATION_TEXTURE_RGB: @@ -1881,260 +1693,518 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, return WINED3D_OK; } +void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_box *box, + const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) +{ + texture->texture_ops->texture_upload_data(texture, sub_resource_idx, + context, box, data, row_pitch, slice_pitch); +} + + /* This call just uploads data, the caller is responsible for binding the * correct texture. */ /* Context activation is done by the caller. */ -void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box, - const struct wined3d_const_bo_address *data, unsigned int src_row_pitch, unsigned int src_slice_pitch, - unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) +static void texture1d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_box *box, const struct wined3d_const_bo_address *data, + unsigned int row_pitch, unsigned int slice_pitch) { + struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface; + const struct wined3d_format *format = texture->resource.format; + unsigned int level = sub_resource_idx % texture->level_count; const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int update_w = src_box->right - src_box->left; - unsigned int update_h = src_box->bottom - src_box->top; - unsigned int update_d = src_box->back - src_box->front; - struct wined3d_bo_address bo; + const void *mem = data->addr; void *converted_mem = NULL; - struct wined3d_format f; - unsigned int level; + unsigned int width, x, update_w; GLenum target; - TRACE("texture %p, sub_resource_idx %u, context %p, format %s, src_box %s, data {%#x:%p}, " - "src_row_pitch %#x, src_slice_pitch %#x, dst_x %u, dst_y %u, dst_z %u, srgb %#x.\n", - texture, sub_resource_idx, context, debug_d3dformat(format->id), debug_box(src_box), - data->buffer_object, data->addr, src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, srgb); + TRACE("texture %p, sub_resource_idx %u, context %p, box %p, data {%#x:%p}, row_pitch %#x, slice_pitch %#x.\n", + texture, sub_resource_idx, context, box, data->buffer_object, data->addr, row_pitch, slice_pitch); + + width = wined3d_texture_get_level_width(texture, level); - if (texture->sub_resources[sub_resource_idx].map_count) + if (!box) { - WARN("Uploading a texture that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n"); - texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM; + x = 0; + update_w = width; } - - if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_HEIGHT_SCALE) + else { - update_h *= format->height_scale.numerator; - update_h /= format->height_scale.denominator; + x = box->left; + update_w = box->right - box->left; } - target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); - level = sub_resource_idx % texture->level_count; + if (format->upload) + { + unsigned int dst_row_pitch; - switch (target) + if (data->buffer_object) + ERR("Loading a converted texture from a PBO.\n"); + if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) + ERR("Converting a block-based format.\n"); + + dst_row_pitch = update_w * format->conv_byte_count; + + converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_row_pitch); + format->upload(data->addr, converted_mem, row_pitch, slice_pitch, dst_row_pitch, dst_row_pitch, update_w, 1, 1); + mem = converted_mem; + } + + if (data->buffer_object) { - case GL_TEXTURE_1D_ARRAY: - dst_y = sub_resource_idx / texture->level_count; - update_h = 1; - break; - case GL_TEXTURE_2D_ARRAY: - dst_z = sub_resource_idx / texture->level_count; - update_d = 1; - break; - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - FIXME("Not supported for multisample textures.\n"); - return; + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object)); + checkGLcall("glBindBuffer"); } - bo.buffer_object = data->buffer_object; - bo.addr = (BYTE *)data->addr + src_box->front * src_slice_pitch; - if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) + target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); + if (target == GL_TEXTURE_1D_ARRAY) { - bo.addr += (src_box->top / format->block_height) * src_row_pitch; - bo.addr += (src_box->left / format->block_width) * format->block_byte_count; + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, row_pitch / format->byte_count); + + gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, x, surface->texture_layer, update_w, 1, format->glFormat, format->glType, mem); + checkGLcall("glTexSubImage2D"); + + gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { - bo.addr += src_box->top * src_row_pitch; - bo.addr += src_box->left * format->byte_count; + gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, x, update_w, format->glFormat, format->glType, mem); + checkGLcall("glTexSubImage1D"); } - if (format->upload) + if (data->buffer_object) { - unsigned int dst_row_pitch, dst_slice_pitch; - void *src_mem; + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); + checkGLcall("glBindBuffer"); + } - if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) - ERR("Converting a block-based format.\n"); + HeapFree(GetProcessHeap(), 0, converted_mem); +} + +/* Context activation is done by the caller. */ +static void texture1d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_bo_address *data) +{ + struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface; + const struct wined3d_format *format = texture->resource.format; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_texture_sub_resource *sub_resource; + BYTE *temporary_mem = NULL; + void *mem; + GLenum target; - f = *format; - f.byte_count = format->conv_byte_count; - format = &f; + sub_resource = &texture->sub_resources[sub_resource_idx]; - wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch); + if (format->conv_byte_count) + { + FIXME("Attempting to download a converted 1d texture, format %s.\n", + debug_d3dformat(format->id)); + return; + } + + target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); + if (target == GL_TEXTURE_1D_ARRAY) + { + WARN_(d3d_perf)("Downloading all miplevel layers to get the surface data for a single sub-resource.\n"); - if (!(converted_mem = heap_calloc(update_d, dst_slice_pitch))) + if (!(temporary_mem = heap_calloc(texture->layer_count, sub_resource->size))) { - ERR("Failed to allocate upload buffer.\n"); + ERR("Out of memory.\n"); return; } - src_mem = context_map_bo_address(context, &bo, src_slice_pitch, - GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ); - format->upload(src_mem, converted_mem, src_row_pitch, src_slice_pitch, - dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d); - context_unmap_bo_address(context, &bo, GL_PIXEL_UNPACK_BUFFER); + mem = temporary_mem; + } + else if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object)); + checkGLcall("glBindBuffer"); + mem = data->addr; + } + else + mem = data->addr; - bo.buffer_object = 0; - bo.addr = converted_mem; - src_row_pitch = dst_row_pitch; - src_slice_pitch = dst_slice_pitch; + gl_info->gl_ops.gl.p_glGetTexImage(target, sub_resource_idx, + format->glFormat, format->glType, mem); + checkGLcall("glGetTexImage"); + + if (temporary_mem) + { + void *src_data = temporary_mem + surface->texture_layer * sub_resource->size; + if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object)); + checkGLcall("glBindBuffer"); + GL_EXTCALL(glBufferSubData(GL_PIXEL_PACK_BUFFER, 0, sub_resource->size, src_data)); + checkGLcall("glBufferSubData"); + } + else + { + memcpy(data->addr, src_data, sub_resource->size); + } } - if (bo.buffer_object) + if (data->buffer_object) { - GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bo.buffer_object)); + GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); checkGLcall("glBindBuffer"); } - if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) + HeapFree(GetProcessHeap(), 0, temporary_mem); +} + +/* Context activation is done by the caller. */ +static void texture1d_srgb_transfer(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, BOOL dest_is_srgb) +{ + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; + unsigned int row_pitch, slice_pitch; + struct wined3d_bo_address data; + + WARN_(d3d_perf)("Performing slow rgb/srgb 1d texture transfer.\n"); + data.buffer_object = 0; + if (!(data.addr = HeapAlloc(GetProcessHeap(), 0, sub_resource->size))) + return; + + wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); + wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb); + texture1d_download_data(texture, sub_resource_idx, context, &data); + wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb); + texture1d_upload_data(texture, sub_resource_idx, context, NULL, + wined3d_const_bo_address(&data), row_pitch, slice_pitch); + + HeapFree(GetProcessHeap(), 0, data.addr); +} + +/* Context activation is done by the caller. */ +static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, DWORD location) +{ + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; + DWORD required_access = wined3d_resource_access_from_location(location); + unsigned int row_pitch, slice_pitch; + + TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", + texture, sub_resource_idx, context, wined3d_debug_location(location)); + + TRACE("Current resource location %s.\n", wined3d_debug_location(sub_resource->locations)); + + if ((sub_resource->locations & location) == location) + { + TRACE("Location(s) already up to date.\n"); + return TRUE; + } + + if ((texture->resource.access & required_access) != required_access) { - unsigned int dst_row_pitch, dst_slice_pitch; - const BYTE *addr = bo.addr; - GLenum internal; + ERR("Operation requires %#x access, but 1d texture only has %#x.\n", + required_access, texture->resource.access); + return FALSE; + } - if (srgb) - internal = format->glGammaInternal; - else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET - && wined3d_resource_is_offscreen(&texture->resource)) - internal = format->rtInternal; - else - internal = format->glInternal; + if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location)) + return FALSE; - wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch); + if (sub_resource->locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("1d texture previously discarded, nothing to do.\n"); + wined3d_texture_validate_location(texture, sub_resource_idx, location); + wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_DISCARDED); + goto done; + } - TRACE("Uploading compressed data, target %#x, level %u, x %u, y %u, z %u, " - "w %u, h %u, d %u, format %#x, image_size %#x, addr %p.\n", - target, level, dst_x, dst_y, dst_z, update_w, update_h, - update_d, internal, dst_slice_pitch, addr); + switch (location) + { + case WINED3D_LOCATION_TEXTURE_RGB: + case WINED3D_LOCATION_TEXTURE_SRGB: + if (sub_resource->locations & WINED3D_LOCATION_SYSMEM) + { + struct wined3d_const_bo_address data = {0, texture->resource.heap_memory}; + data.addr += sub_resource->offset; + wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); + wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); + texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); + } + else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) + { +#if !defined(STAGING_CSMT) + struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL}; +#else /* STAGING_CSMT */ + struct wined3d_const_bo_address data = {sub_resource->buffer->name, NULL}; +#endif /* STAGING_CSMT */ + wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); + wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); + texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); + } + else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) + { + texture1d_srgb_transfer(texture, sub_resource_idx, context, TRUE); + } + else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_SRGB) + { + texture1d_srgb_transfer(texture, sub_resource_idx, context, FALSE); + } + else + { + FIXME("Implement 1d texture loading from %s.\n", wined3d_debug_location(sub_resource->locations)); + return FALSE; + } + break; - if (target == GL_TEXTURE_1D) - { - GL_EXTCALL(glCompressedTexSubImage1D(target, level, dst_x, - update_w, internal, dst_row_pitch, addr)); - } - else if (dst_row_pitch == src_row_pitch) - { - if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) + case WINED3D_LOCATION_SYSMEM: + if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { - GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, dst_y, dst_z, - update_w, update_h, update_d, internal, dst_slice_pitch * update_d, addr)); + struct wined3d_bo_address data = {0, texture->resource.heap_memory}; + + data.addr += sub_resource->offset; + if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(texture, context, FALSE); + else + wined3d_texture_bind_and_dirtify(texture, context, TRUE); + + texture1d_download_data(texture, sub_resource_idx, context, &data); + ++texture->download_count; } else { - GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, dst_y, - update_w, update_h, internal, dst_slice_pitch, addr)); + FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", + wined3d_debug_location(sub_resource->locations)); + return FALSE; } - } - else - { - unsigned int row_count = (update_h + format->block_height - 1) / format->block_height; - unsigned int row, y, z; + break; - /* glCompressedTexSubImage2D() ignores pixel store state, so we - * can't use the unpack row length like for glTexSubImage2D. */ - for (z = dst_z; z < dst_z + update_d; ++z) + case WINED3D_LOCATION_BUFFER: + if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { - for (row = 0, y = dst_y; row < row_count; ++row) - { - if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) - { - GL_EXTCALL(glCompressedTexSubImage3D(target, level, dst_x, y, z, - update_w, format->block_height, 1, internal, dst_row_pitch, addr)); - } - else - { - GL_EXTCALL(glCompressedTexSubImage2D(target, level, dst_x, y, - update_w, format->block_height, internal, dst_row_pitch, addr)); - } - - y += format->block_height; - addr += src_row_pitch; - } +#if !defined(STAGING_CSMT) + struct wined3d_bo_address data = {sub_resource->buffer_object, NULL}; +#else /* STAGING_CSMT */ + struct wined3d_bo_address data = {sub_resource->buffer->name, NULL}; +#endif /* STAGING_CSMT */ + + if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(texture, context, FALSE); + else + wined3d_texture_bind_and_dirtify(texture, context, TRUE); + + texture1d_download_data(texture, sub_resource_idx, context, &data); } - } - checkGLcall("Upload compressed texture data"); + else + { + FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", + wined3d_debug_location(sub_resource->locations)); + return FALSE; + } + break; + + default: + FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), + wined3d_debug_location(sub_resource->locations)); + return FALSE; } + +done: + wined3d_texture_validate_location(texture, sub_resource_idx, location); + + return TRUE; +} + +static void texture1d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) +{ + const struct wined3d_format *format = texture->resource.format; + unsigned int sub_count = texture->level_count * texture->layer_count; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int width; + GLenum internal; + + wined3d_texture_bind_and_dirtify(texture, context, srgb); + + if (srgb) + internal = format->glGammaInternal; + else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET + && wined3d_resource_is_offscreen(&texture->resource)) + internal = format->rtInternal; else + internal = format->glInternal; + + if (wined3d_texture_use_immutable_storage(texture, gl_info)) { - TRACE("Uploading data, target %#x, level %u, x %u, y %u, z %u, " - "w %u, h %u, d %u, format %#x, type %#x, addr %p.\n", - target, level, dst_x, dst_y, dst_z, update_w, update_h, - update_d, format->glFormat, format->glType, bo.addr); + width = wined3d_texture_get_level_width(texture, 0); - gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_row_pitch / format->byte_count); - if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D) - { - GL_EXTCALL(glTexSubImage3D(target, level, dst_x, dst_y, dst_z, - update_w, update_h, update_d, format->glFormat, format->glType, bo.addr)); - } - else if (target == GL_TEXTURE_1D) + if (texture->target == GL_TEXTURE_1D_ARRAY) { - gl_info->gl_ops.gl.p_glTexSubImage1D(target, level, dst_x, - update_w, format->glFormat, format->glType, bo.addr); + GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count, internal, width, texture->layer_count)); + checkGLcall("glTexStorage2D"); } else { - gl_info->gl_ops.gl.p_glTexSubImage2D(target, level, dst_x, dst_y, - update_w, update_h, format->glFormat, format->glType, bo.addr); + GL_EXTCALL(glTexStorage1D(texture->target, texture->level_count, internal, width)); + checkGLcall("glTexStorage1D"); } - gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - checkGLcall("Upload texture data"); - } - - if (bo.buffer_object) - { - GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); - checkGLcall("glBindBuffer"); } - heap_free(converted_mem); - - if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE) + else { - struct wined3d_device *device = texture->resource.device; unsigned int i; - for (i = 0; i < device->context_count; ++i) + for (i = 0; i < sub_count; ++i) { - context_texture_update(device->contexts[i], texture); + GLenum target; + struct wined3d_surface *surface = texture->sub_resources[i].u.surface; + width = wined3d_texture_get_level_width(texture, surface->texture_level); + target = wined3d_texture_get_sub_resource_target(texture, i); + + if (texture->target == GL_TEXTURE_1D_ARRAY) + { + gl_info->gl_ops.gl.p_glTexImage2D(target, surface->texture_level, + internal, width, texture->layer_count, 0, format->glFormat, format->glType, NULL); + checkGLcall("glTexImage2D"); + } + else + { + gl_info->gl_ops.gl.p_glTexImage1D(target, surface->texture_level, + internal, width, 0, format->glFormat, format->glType, NULL); + checkGLcall("glTexImage1D"); + } } } } -/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ +static void texture1d_cleanup_sub_resources(struct wined3d_texture *texture) +{ +} + +static const struct wined3d_texture_ops texture1d_ops = +{ + texture1d_upload_data, + texture1d_load_location, + texture1d_prepare_texture, + texture1d_cleanup_sub_resources, +}; + +static void texture2d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_box *box, + const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) +{ + unsigned int texture_level; + POINT dst_point; + RECT src_rect; + + src_rect.left = 0; + src_rect.top = 0; + if (box) + { + dst_point.x = box->left; + dst_point.y = box->top; + src_rect.right = box->right - box->left; + src_rect.bottom = box->bottom - box->top; + } + else + { + dst_point.x = dst_point.y = 0; + texture_level = sub_resource_idx % texture->level_count; + src_rect.right = wined3d_texture_get_level_width(texture, texture_level); + src_rect.bottom = wined3d_texture_get_level_height(texture, texture_level); + } + + wined3d_surface_upload_data(texture->sub_resources[sub_resource_idx].u.surface, context->gl_info, + texture->resource.format, &src_rect, row_pitch, &dst_point, FALSE, data); +} + static BOOL texture2d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location) { - TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", - texture, sub_resource_idx, context, wined3d_debug_location(location)); + return surface_load_location(texture->sub_resources[sub_resource_idx].u.surface, context, location); +} - switch (location) +/* Context activation is done by the caller. */ +static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) +{ + const struct wined3d_format *format = texture->resource.format; + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_color_key_conversion *conversion; + GLenum internal; + + TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id)); + + if (format->conv_byte_count) { - case WINED3D_LOCATION_USER_MEMORY: - case WINED3D_LOCATION_SYSMEM: - case WINED3D_LOCATION_BUFFER: - return texture2d_load_sysmem(texture, sub_resource_idx, context, location); + texture->flags |= WINED3D_TEXTURE_CONVERTED; + } + else if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE))) + { + texture->flags |= WINED3D_TEXTURE_CONVERTED; + format = wined3d_get_format(gl_info, conversion->dst_format, texture->resource.usage); + TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format->id)); + } + + wined3d_texture_bind_and_dirtify(texture, context, srgb); + + if (srgb) + internal = format->glGammaInternal; + else if (texture->resource.usage & WINED3DUSAGE_RENDERTARGET + && wined3d_resource_is_offscreen(&texture->resource)) + internal = format->rtInternal; + else + internal = format->glInternal; + + if (!internal) + FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id)); + + TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType); + + if (wined3d_texture_use_immutable_storage(texture, gl_info)) + wined3d_texture_allocate_gl_immutable_storage(texture, internal, gl_info); + else + wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info); +} + +static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture) +{ + unsigned int sub_count = texture->level_count * texture->layer_count; + struct wined3d_device *device = texture->resource.device; + struct wined3d_texture_sub_resource *sub_resource; + struct wined3d_renderbuffer_entry *entry, *entry2; + const struct wined3d_gl_info *gl_info = NULL; + struct wined3d_context *context = NULL; + struct wined3d_surface *surface; + unsigned int i; + + for (i = 0; i < sub_count; ++i) + { + sub_resource = &texture->sub_resources[i]; + if (!(surface = sub_resource->u.surface)) + continue; - case WINED3D_LOCATION_DRAWABLE: - return texture2d_load_drawable(texture, sub_resource_idx, context); + TRACE("surface %p.\n", surface); - case WINED3D_LOCATION_RB_RESOLVED: - case WINED3D_LOCATION_RB_MULTISAMPLE: - return texture2d_load_renderbuffer(texture, sub_resource_idx, context, location); + if (!context && !list_empty(&surface->renderbuffers)) + { + context = context_acquire(device, NULL, 0); + gl_info = context->gl_info; + } - case WINED3D_LOCATION_TEXTURE_RGB: - case WINED3D_LOCATION_TEXTURE_SRGB: - return texture2d_load_texture(texture, sub_resource_idx, context, - location == WINED3D_LOCATION_TEXTURE_SRGB); + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry) + { + TRACE("Deleting renderbuffer %u.\n", entry->id); + context_gl_resource_released(device, entry->id, TRUE); + gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id); + heap_free(entry); + } - default: - ERR("Don't know how to handle location %#x.\n", location); - return FALSE; + if (surface->dc) + texture2d_destroy_dc(surface); } + if (context) + context_release(context); + heap_free(texture->sub_resources[0].u.surface); } static const struct wined3d_texture_ops texture2d_ops = { + texture2d_upload_data, texture2d_load_location, + texture2d_prepare_texture, + texture2d_cleanup_sub_resources, }; struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource) @@ -2166,7 +2236,6 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) { struct wined3d_texture *texture = texture_from_resource(resource); UINT sub_count = texture->level_count * texture->layer_count; - struct wined3d_renderbuffer_entry *entry, *entry2; struct wined3d_device *device = resource->device; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; @@ -2199,19 +2268,30 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_DISCARDED); } +#if !defined(STAGING_CSMT) if (sub_resource->buffer_object) wined3d_texture_remove_buffer_object(texture, i, context->gl_info); - } +#else /* STAGING_CSMT */ + if (sub_resource->buffer) + wined3d_texture_remove_buffer_object(texture, i, context); +#endif /* STAGING_CSMT */ - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry) - { - context_gl_resource_released(device, entry->id, TRUE); - gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id); - list_remove(&entry->entry); - heap_free(entry); + if (resource->type == WINED3D_RTYPE_TEXTURE_2D) + { + struct wined3d_surface *surface = sub_resource->u.surface; + struct wined3d_renderbuffer_entry *entry, *entry2; + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry) + { + context_gl_resource_released(device, entry->id, TRUE); + gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id); + list_remove(&entry->entry); + heap_free(entry); + } + list_init(&surface->renderbuffers); + surface->current_renderbuffer = NULL; + } } - list_init(&texture->renderbuffers); - texture->current_renderbuffer = NULL; context_release(context); @@ -2435,179 +2515,140 @@ static const struct wined3d_resource_ops texture_resource_ops = texture_resource_sub_resource_unmap, }; -/* Context activation is done by the caller. */ -static void texture1d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, - const struct wined3d_context *context, const struct wined3d_bo_address *data) +static HRESULT texture1d_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, + UINT layer_count, UINT level_count, struct wined3d_device *device, void *parent, + const struct wined3d_parent_ops *parent_ops) { - const struct wined3d_format *format = texture->resource.format; - const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_device_parent *device_parent = device->device_parent; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_surface *surfaces; + unsigned int i, j; + HRESULT hr; - if (format->conv_byte_count) + if (layer_count > 1 && !gl_info->supported[EXT_TEXTURE_ARRAY]) { - FIXME("Attempting to download a converted texture, format %s.\n", - debug_d3dformat(format->id)); - return; + WARN("OpenGL implementation does not support array textures.\n"); + return WINED3DERR_INVALIDCALL; } - if (data->buffer_object) + /* TODO: It should only be possible to create textures for formats + * that are reported as supported. */ + if (WINED3DFMT_UNKNOWN >= desc->format) { - GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, data->buffer_object)); - checkGLcall("glBindBuffer"); + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); + return WINED3DERR_INVALIDCALL; } - gl_info->gl_ops.gl.p_glGetTexImage(texture->target, sub_resource_idx, - format->glFormat, format->glType, data->addr); - checkGLcall("glGetTexImage"); - - if (data->buffer_object) + if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) { - GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); - checkGLcall("glBindBuffer"); + WARN("1d textures can not be used for cube mapping, returning D3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; } -} - -/* Context activation is done by the caller. */ -static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, DWORD location) -{ - struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; - unsigned int row_pitch, slice_pitch; - TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", - texture, sub_resource_idx, context, wined3d_debug_location(location)); + if ((desc->usage & WINED3DUSAGE_DYNAMIC && wined3d_resource_access_is_managed(desc->access)) + || (desc->usage & WINED3DUSAGE_SCRATCH)) + { + WARN("Attempted to create a DYNAMIC texture in pool %s.\n", wined3d_debug_resource_access(desc->access)); + return WINED3DERR_INVALIDCALL; + } - if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location)) - return FALSE; + if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && !is_power_of_two(desc->width)) + { + if (desc->usage & WINED3DUSAGE_SCRATCH) + { + WARN("Creating a scratch NPOT 1d texture despite lack of HW support.\n"); + } + else + { + WARN("Attempted to create a NPOT 1d texture (%u, %u, %u) without GL support.\n", + desc->width, desc->height, desc->depth); + return WINED3DERR_INVALIDCALL; + } + } - switch (location) + if (desc->usage & WINED3DUSAGE_QUERY_GENMIPMAP) { - case WINED3D_LOCATION_TEXTURE_RGB: - case WINED3D_LOCATION_TEXTURE_SRGB: - if (sub_resource->locations & WINED3D_LOCATION_SYSMEM) - { - struct wined3d_const_bo_address data = {0, texture->resource.heap_memory}; - struct wined3d_box src_box; + if (level_count != 1) + { + WARN("WINED3DUSAGE_QUERY_GENMIPMAP is set, and level count != 1, returning WINED3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + } - data.addr += sub_resource->offset; - wined3d_texture_bind_and_dirtify(texture, context, - location == WINED3D_LOCATION_TEXTURE_SRGB); - wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); - wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box); - wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format, - &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE); - } - else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) - { - struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL}; - struct wined3d_box src_box; + if (FAILED(hr = wined3d_texture_init(texture, &texture1d_ops, layer_count, level_count, desc, + 0, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); + return hr; + } - wined3d_texture_bind_and_dirtify(texture, context, - location == WINED3D_LOCATION_TEXTURE_SRGB); - wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); - wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box); - wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format, - &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE); - } - else - { - FIXME("Implement texture loading from %s.\n", wined3d_debug_location(sub_resource->locations)); - return FALSE; - } - break; + texture->pow2_matrix[0] = 1.0f; + texture->pow2_matrix[5] = 1.0f; + texture->pow2_matrix[10] = 1.0f; + texture->pow2_matrix[15] = 1.0f; + texture->target = (layer_count > 1) ? GL_TEXTURE_1D_ARRAY : GL_TEXTURE_1D; - case WINED3D_LOCATION_SYSMEM: - if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) - { - struct wined3d_bo_address data = {0, texture->resource.heap_memory}; + if (wined3d_texture_use_pbo(texture, gl_info)) + { + wined3d_resource_free_sysmem(&texture->resource); + texture->resource.map_binding = WINED3D_LOCATION_BUFFER; + } - data.addr += sub_resource->offset; - if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) - wined3d_texture_bind_and_dirtify(texture, context, FALSE); - else - wined3d_texture_bind_and_dirtify(texture, context, TRUE); + if (level_count > ~(SIZE_T)0 / layer_count + || !(surfaces = heap_calloc(level_count * layer_count, sizeof(*surfaces)))) + { + wined3d_texture_cleanup_sync(texture); + return E_OUTOFMEMORY; + } - texture1d_download_data(texture, sub_resource_idx, context, &data); - ++texture->download_count; - } - else + /* Generate all the surfaces. */ + for (i = 0; i < texture->level_count; ++i) + { + for (j = 0; j < texture->layer_count; ++j) + { + struct wined3d_texture_sub_resource *sub_resource; + unsigned int idx = j * texture->level_count + i; + struct wined3d_surface *surface; + + surface = &surfaces[idx]; + surface->container = texture; + surface->texture_level = i; + surface->texture_layer = j; + list_init(&surface->renderbuffers); + + sub_resource = &texture->sub_resources[idx]; + sub_resource->locations = WINED3D_LOCATION_DISCARDED; + sub_resource->u.surface = surface; + + if (FAILED(hr = device_parent->ops->surface_created(device_parent, + texture, idx, &sub_resource->parent, &sub_resource->parent_ops))) { - FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", - wined3d_debug_location(sub_resource->locations)); - return FALSE; + WARN("Failed to create texture1d parent, hr %#x.\n", hr); + sub_resource->parent = NULL; + wined3d_texture_cleanup_sync(texture); + return hr; } - break; - - case WINED3D_LOCATION_BUFFER: - if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) - { - struct wined3d_bo_address data = {sub_resource->buffer_object, NULL}; - - if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) - wined3d_texture_bind_and_dirtify(texture, context, FALSE); - else - wined3d_texture_bind_and_dirtify(texture, context, TRUE); - texture1d_download_data(texture, sub_resource_idx, context, &data); - } - else - { - FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", - wined3d_debug_location(sub_resource->locations)); - return FALSE; - } - break; + TRACE("parent %p, parent_ops %p.\n", parent, parent_ops); - default: - FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), - wined3d_debug_location(sub_resource->locations)); - return FALSE; + TRACE("Created 1d texture surface level %u, layer %u @ %p.\n", i, j, surface); + } } - return TRUE; + return WINED3D_OK; } -static const struct wined3d_texture_ops texture1d_ops = -{ - texture1d_load_location, -}; - -static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, +static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count, DWORD flags, struct wined3d_device *device, - void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_texture_ops *texture_ops) + void *parent, const struct wined3d_parent_ops *parent_ops) { struct wined3d_device_parent *device_parent = device->device_parent; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - unsigned int sub_count, i, j, size, offset = 0; - unsigned int pow2_width, pow2_height; - const struct wined3d_format *format; + struct wined3d_surface *surfaces; + UINT pow2_width, pow2_height; + unsigned int i, j, sub_count; HRESULT hr; - TRACE("texture %p, resource_type %s, format %s, multisample_type %#x, multisample_quality %#x, " - "usage %s, access %s, width %u, height %u, depth %u, layer_count %u, level_count %u, " - "flags %#x, device %p, parent %p, parent_ops %p, texture_ops %p.\n", - texture, debug_d3dresourcetype(desc->resource_type), debug_d3dformat(desc->format), - desc->multisample_type, desc->multisample_quality, debug_d3dusage(desc->usage), - wined3d_debug_resource_access(desc->access), desc->width, desc->height, desc->depth, - layer_count, level_count, flags, device, parent, parent_ops, texture_ops); - - if (!desc->width || !desc->height || !desc->depth) - return WINED3DERR_INVALIDCALL; - - if (desc->resource_type == WINED3D_RTYPE_TEXTURE_3D) - { - if (layer_count != 1) - { - ERR("Invalid layer count for volume texture.\n"); - return E_INVALIDARG; - } - - if (!gl_info->supported[EXT_TEXTURE3D]) - { - WARN("OpenGL implementation does not support 3D textures.\n"); - return WINED3DERR_INVALIDCALL; - } - } - if (!(desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) && layer_count > 1 && !gl_info->supported[EXT_TEXTURE_ARRAY]) { @@ -2619,18 +2660,12 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc * that are reported as supported. */ if (WINED3DFMT_UNKNOWN >= desc->format) { - WARN("Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n"); - return WINED3DERR_INVALIDCALL; - } - - if (desc->usage & WINED3DUSAGE_DYNAMIC && (wined3d_resource_access_is_managed(desc->access) - || desc->usage & WINED3DUSAGE_SCRATCH)) - { - WARN("Attempted to create a dynamic texture with access %s and usage %s.\n", - wined3d_debug_resource_access(desc->access), debug_d3dusage(desc->usage)); + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); return WINED3DERR_INVALIDCALL; } + if (desc->usage & WINED3DUSAGE_DYNAMIC && wined3d_resource_access_is_managed(desc->access)) + FIXME("Trying to create a managed texture with dynamic usage.\n"); if (!(desc->usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)) && (flags & WINED3D_TEXTURE_CREATE_MAPPABLE)) WARN("Creating a mappable texture that doesn't specify dynamic usage.\n"); @@ -2639,16 +2674,15 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc pow2_width = desc->width; pow2_height = desc->height; - if (((desc->width & (desc->width - 1)) || (desc->height & (desc->height - 1)) || (desc->depth & (desc->depth - 1))) + if (((desc->width & (desc->width - 1)) || (desc->height & (desc->height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { /* level_count == 0 returns an error as well. */ - if (level_count != 1 || layer_count != 1 || desc->resource_type == WINED3D_RTYPE_TEXTURE_3D) + if (level_count != 1 || layer_count != 1) { if (!(desc->usage & WINED3DUSAGE_SCRATCH)) { - WARN("Attempted to create a mipmapped/cube/array/volume NPOT " - "texture without unconditional NPOT support.\n"); + WARN("Attempted to create a mipmapped/cube/array NPOT texture without unconditional NPOT support.\n"); return WINED3DERR_INVALIDCALL; } @@ -2656,8 +2690,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc } texture->flags |= WINED3D_TEXTURE_COND_NP2; - if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !gl_info->supported[ARB_TEXTURE_RECTANGLE] - && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]) + if (!gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]) { const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format, desc->usage); @@ -2696,115 +2729,20 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc * 16 and a width > 3000 and blt 16x16 letter areas from them to * the render target. */ if (desc->access & WINED3D_RESOURCE_ACCESS_GPU) - { - WARN("Dimensions (%ux%u) exceed the maximum texture size.\n", pow2_width, pow2_height); - return WINED3DERR_NOTAVAILABLE; - } - - /* We should never use this surface in combination with OpenGL. */ - TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width, pow2_height); - } - - format = wined3d_get_format(&device->adapter->gl_info, desc->format, desc->usage); - for (i = 0; i < layer_count; ++i) - { - for (j = 0; j < level_count; ++j) - { - unsigned int idx = i * level_count + j; - - size = wined3d_format_calculate_size(format, device->surface_alignment, - max(1, desc->width >> j), max(1, desc->height >> j), max(1, desc->depth >> j)); - texture->sub_resources[idx].offset = offset; - texture->sub_resources[idx].size = size; - offset += size; - } - offset = (offset + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1); - } - - if (!offset) - return WINED3DERR_INVALIDCALL; - - if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format, - desc->multisample_type, desc->multisample_quality, desc->usage, desc->access, - desc->width, desc->height, desc->depth, offset, parent, parent_ops, &texture_resource_ops))) - { - static unsigned int once; - - /* DXTn 3D textures are not supported. Do not write the ERR for them. */ - if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3 - || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5) - && !(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE) - && desc->resource_type != WINED3D_RTYPE_TEXTURE_3D && !once++) - ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n"); - - WARN("Failed to initialize resource, returning %#x\n", hr); - return hr; - } - wined3d_resource_update_draw_binding(&texture->resource); - if ((flags & WINED3D_TEXTURE_CREATE_MAPPABLE) || desc->format == WINED3DFMT_D16_LOCKABLE) - texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; - - texture->texture_ops = texture_ops; - - texture->layer_count = layer_count; - texture->level_count = level_count; - texture->lod = 0; - texture->flags |= WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS; - if (flags & WINED3D_TEXTURE_CREATE_GET_DC_LENIENT) - texture->flags |= WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_GET_DC_LENIENT; - if (flags & (WINED3D_TEXTURE_CREATE_GET_DC | WINED3D_TEXTURE_CREATE_GET_DC_LENIENT)) - texture->flags |= WINED3D_TEXTURE_GET_DC; - if (flags & WINED3D_TEXTURE_CREATE_DISCARD) - texture->flags |= WINED3D_TEXTURE_DISCARD; - if (flags & WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS) - { - if (!(texture->resource.format_flags & WINED3DFMT_FLAG_GEN_MIPMAP)) - WARN("Format doesn't support mipmaps generation, " - "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n"); - else - texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS; - } + { + WARN("Dimensions (%ux%u) exceed the maximum texture size.\n", pow2_width, pow2_height); + return WINED3DERR_NOTAVAILABLE; + } - list_init(&texture->renderbuffers); + /* We should never use this surface in combination with OpenGL. */ + TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width, pow2_height); + } - switch (desc->resource_type) + if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, layer_count, level_count, desc, + flags, device, parent, parent_ops, &texture_resource_ops))) { - case WINED3D_RTYPE_TEXTURE_1D: - if (layer_count > 1) - texture->target = GL_TEXTURE_1D_ARRAY; - else - texture->target = GL_TEXTURE_1D; - break; - - case WINED3D_RTYPE_TEXTURE_2D: - if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) - { - texture->target = GL_TEXTURE_CUBE_MAP_ARB; - } - else if (desc->multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) - { - if (layer_count > 1) - texture->target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; - else - texture->target = GL_TEXTURE_2D_MULTISAMPLE; - } - else - { - if (layer_count > 1) - texture->target = GL_TEXTURE_2D_ARRAY; - else - texture->target = GL_TEXTURE_2D; - } - break; - - case WINED3D_RTYPE_TEXTURE_3D: - texture->target = GL_TEXTURE_3D; - break; - - default: - ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type)); - wined3d_texture_cleanup_sync(texture); - return WINED3DERR_INVALIDCALL; + WARN("Failed to initialize texture, returning %#x.\n", hr); + return hr; } /* Precalculated scaling for 'faked' non power of two texture coords. */ @@ -2815,16 +2753,37 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc texture->flags &= ~(WINED3D_TEXTURE_POW2_MAT_IDENT | WINED3D_TEXTURE_NORMALIZED_COORDS); texture->target = GL_TEXTURE_RECTANGLE_ARB; } - else if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) - { - texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width)); - texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height)); - texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT; - } else { - texture->pow2_matrix[0] = 1.0f; - texture->pow2_matrix[5] = 1.0f; + if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) + { + texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width)); + texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height)); + texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT; + } + else + { + texture->pow2_matrix[0] = 1.0f; + texture->pow2_matrix[5] = 1.0f; + } + if (desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) + { + texture->target = GL_TEXTURE_CUBE_MAP_ARB; + } + else if (desc->multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) + { + if (layer_count > 1) + texture->target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + else + texture->target = GL_TEXTURE_2D_MULTISAMPLE; + } + else + { + if (layer_count > 1) + texture->target = GL_TEXTURE_2D_ARRAY; + else + texture->target = GL_TEXTURE_2D; + } } texture->pow2_matrix[10] = 1.0f; texture->pow2_matrix[15] = 1.0f; @@ -2833,19 +2792,9 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc if (wined3d_texture_use_pbo(texture, gl_info)) texture->resource.map_binding = WINED3D_LOCATION_BUFFER; - if ((desc->resource_type != WINED3D_RTYPE_TEXTURE_3D - && !(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)) - || !wined3d_texture_use_pbo(texture, gl_info)) - { - if (!wined3d_resource_allocate_sysmem(&texture->resource)) - { - wined3d_texture_cleanup_sync(texture); - return E_OUTOFMEMORY; - } - } - sub_count = level_count * layer_count; - if (sub_count / layer_count != level_count) + if (sub_count / layer_count != level_count + || !(surfaces = heap_calloc(sub_count, sizeof(*surfaces)))) { wined3d_texture_cleanup_sync(texture); return E_OUTOFMEMORY; @@ -2855,6 +2804,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc { if (!(texture->overlay_info = heap_calloc(sub_count, sizeof(*texture->overlay_info)))) { + heap_free(surfaces); wined3d_texture_cleanup_sync(texture); return E_OUTOFMEMORY; } @@ -2866,44 +2816,52 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc } } - /* Generate all sub-resources. */ - for (i = 0; i < sub_count; ++i) + /* Generate all the surfaces. */ + for (i = 0; i < texture->level_count; ++i) { - struct wined3d_texture_sub_resource *sub_resource; - - sub_resource = &texture->sub_resources[i]; - sub_resource->locations = WINED3D_LOCATION_DISCARDED; - if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D - && !(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)) + for (j = 0; j < texture->layer_count; ++j) { - wined3d_texture_validate_location(texture, i, WINED3D_LOCATION_SYSMEM); - wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_SYSMEM); - } - - if (FAILED(hr = device_parent->ops->texture_sub_resource_created(device_parent, - desc->resource_type, texture, i, &sub_resource->parent, &sub_resource->parent_ops))) - { - WARN("Failed to create sub-resource parent, hr %#x.\n", hr); - sub_resource->parent = NULL; - wined3d_texture_cleanup_sync(texture); - return hr; - } + struct wined3d_texture_sub_resource *sub_resource; + unsigned int idx = j * texture->level_count + i; + struct wined3d_surface *surface; + + surface = &surfaces[idx]; + surface->container = texture; + surface->texture_level = i; + surface->texture_layer = j; + list_init(&surface->renderbuffers); + + sub_resource = &texture->sub_resources[idx]; + sub_resource->locations = WINED3D_LOCATION_DISCARDED; + sub_resource->u.surface = surface; + if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)) + { + wined3d_texture_validate_location(texture, idx, WINED3D_LOCATION_SYSMEM); + wined3d_texture_invalidate_location(texture, idx, ~WINED3D_LOCATION_SYSMEM); + } - TRACE("parent %p, parent_ops %p.\n", sub_resource->parent, sub_resource->parent_ops); + if (FAILED(hr = device_parent->ops->surface_created(device_parent, + texture, idx, &sub_resource->parent, &sub_resource->parent_ops))) + { + WARN("Failed to create surface parent, hr %#x.\n", hr); + sub_resource->parent = NULL; + wined3d_texture_cleanup_sync(texture); + return hr; + } - TRACE("Created sub-resource %u (level %u, layer %u).\n", - i, i % texture->level_count, i / texture->level_count); + TRACE("parent %p, parent_ops %p.\n", sub_resource->parent, sub_resource->parent_ops); - if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) - { - struct wined3d_texture_idx texture_idx = {texture, i}; + TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface); - wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx); - device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - if (!texture->dc_info || !texture->dc_info[i].dc) + if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) { - wined3d_texture_cleanup_sync(texture); - return WINED3DERR_INVALIDCALL; + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); + device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); + if (!surface->dc) + { + wined3d_texture_cleanup_sync(texture); + return WINED3DERR_INVALIDCALL; + } } } } @@ -2911,6 +2869,88 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc return WINED3D_OK; } +/* This call just uploads data, the caller is responsible for binding the + * correct texture. */ +/* Context activation is done by the caller. */ +static void texture3d_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_box *box, + const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) +{ + const struct wined3d_format *format = texture->resource.format; + unsigned int level = sub_resource_idx % texture->level_count; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int x, y, z, update_w, update_h, update_d; + unsigned int dst_row_pitch, dst_slice_pitch; + unsigned int width, height, depth; + const void *mem = data->addr; + void *converted_mem = NULL; + + TRACE("texture %p, sub_resource_idx %u, context %p, box %s, data {%#x:%p}, row_pitch %#x, slice_pitch %#x.\n", + texture, sub_resource_idx, context, debug_box(box), + data->buffer_object, data->addr, row_pitch, slice_pitch); + + width = wined3d_texture_get_level_width(texture, level); + height = wined3d_texture_get_level_height(texture, level); + depth = wined3d_texture_get_level_depth(texture, level); + + if (!box) + { + x = y = z = 0; + update_w = width; + update_h = height; + update_d = depth; + } + else + { + x = box->left; + y = box->top; + z = box->front; + update_w = box->right - box->left; + update_h = box->bottom - box->top; + update_d = box->back - box->front; + } + + if (format->conv_byte_count) + { + if (data->buffer_object) + ERR("Loading a converted texture from a PBO.\n"); + if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) + ERR("Converting a block-based format.\n"); + + dst_row_pitch = update_w * format->conv_byte_count; + dst_slice_pitch = dst_row_pitch * update_h; + + converted_mem = heap_calloc(update_d, dst_slice_pitch); + format->upload(data->addr, converted_mem, row_pitch, slice_pitch, + dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d); + mem = converted_mem; + } + else + { + wined3d_texture_get_pitch(texture, sub_resource_idx, &dst_row_pitch, &dst_slice_pitch); + if (row_pitch != dst_row_pitch || slice_pitch != dst_slice_pitch) + FIXME("Ignoring row/slice pitch (%u/%u).\n", row_pitch, slice_pitch); + } + + if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, data->buffer_object)); + checkGLcall("glBindBuffer"); + } + + GL_EXTCALL(glTexSubImage3D(GL_TEXTURE_3D, level, x, y, z, + update_w, update_h, update_d, format->glFormat, format->glType, mem)); + checkGLcall("glTexSubImage3D"); + + if (data->buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); + checkGLcall("glBindBuffer"); + } + + heap_free(converted_mem); +} + /* Context activation is done by the caller. */ static void texture3d_download_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, const struct wined3d_context *context, const struct wined3d_bo_address *data) @@ -2950,7 +2990,6 @@ static void texture3d_srgb_transfer(struct wined3d_texture *texture, unsigned in struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; unsigned int row_pitch, slice_pitch; struct wined3d_bo_address data; - struct wined3d_box src_box; /* Optimisations are possible, but the effort should be put into either * implementing EXT_SRGB_DECODE in the driver or finding out why we @@ -2964,12 +3003,11 @@ static void texture3d_srgb_transfer(struct wined3d_texture *texture, unsigned in return; wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); - wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box); wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb); texture3d_download_data(texture, sub_resource_idx, context, &data); wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb); - wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format, - &src_box, wined3d_const_bo_address(&data), row_pitch, slice_pitch, 0, 0, 0, FALSE); + texture3d_upload_data(texture, sub_resource_idx, context, + NULL, wined3d_const_bo_address(&data), row_pitch, slice_pitch); heap_free(data.addr); } @@ -2991,27 +3029,23 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in if (sub_resource->locations & WINED3D_LOCATION_SYSMEM) { struct wined3d_const_bo_address data = {0, texture->resource.heap_memory}; - struct wined3d_box src_box; - data.addr += sub_resource->offset; wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); - wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box); - wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format, - &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE); + texture3d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); } else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) { +#if !defined(STAGING_CSMT) struct wined3d_const_bo_address data = {sub_resource->buffer_object, NULL}; - struct wined3d_box src_box; - +#else /* STAGING_CSMT */ + struct wined3d_const_bo_address data = {sub_resource->buffer->name, NULL}; +#endif /* STAGING_CSMT */ wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); - wined3d_texture_get_level_box(texture, sub_resource_idx % texture->level_count, &src_box); - wined3d_texture_upload_data(texture, sub_resource_idx, context, texture->resource.format, - &src_box, &data, row_pitch, slice_pitch, 0, 0, 0, FALSE); + texture3d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); } else if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) { @@ -3053,7 +3087,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { +#if !defined(STAGING_CSMT) struct wined3d_bo_address data = {sub_resource->buffer_object, NULL}; +#else /* STAGING_CSMT */ + struct wined3d_bo_address data = {sub_resource->buffer->name, NULL}; +#endif /* STAGING_CSMT */ if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); @@ -3079,11 +3117,148 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in return TRUE; } +static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) +{ + const struct wined3d_format *format = texture->resource.format; + GLenum internal = srgb ? format->glGammaInternal : format->glInternal; + unsigned int sub_count = texture->level_count * texture->layer_count; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int i; + + wined3d_texture_bind_and_dirtify(texture, context, srgb); + + if (wined3d_texture_use_immutable_storage(texture, gl_info)) + { + GL_EXTCALL(glTexStorage3D(GL_TEXTURE_3D, texture->level_count, internal, + wined3d_texture_get_level_width(texture, 0), + wined3d_texture_get_level_height(texture, 0), + wined3d_texture_get_level_depth(texture, 0))); + checkGLcall("glTexStorage3D"); + } + else + { + for (i = 0; i < sub_count; ++i) + { + GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D, i, internal, + wined3d_texture_get_level_width(texture, i), + wined3d_texture_get_level_height(texture, i), + wined3d_texture_get_level_depth(texture, i), + 0, format->glFormat, format->glType, NULL)); + checkGLcall("glTexImage3D"); + } + } +} + +static void texture3d_cleanup_sub_resources(struct wined3d_texture *texture) +{ +} + static const struct wined3d_texture_ops texture3d_ops = { + texture3d_upload_data, texture3d_load_location, + texture3d_prepare_texture, + texture3d_cleanup_sub_resources, }; +static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, + UINT layer_count, UINT level_count, DWORD flags, struct wined3d_device *device, void *parent, + const struct wined3d_parent_ops *parent_ops) +{ + struct wined3d_device_parent *device_parent = device->device_parent; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + unsigned int i; + HRESULT hr; + + if (layer_count != 1) + { + ERR("Invalid layer count for volume texture.\n"); + return E_INVALIDARG; + } + + /* TODO: It should only be possible to create textures for formats + * that are reported as supported. */ + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); + return WINED3DERR_INVALIDCALL; + } + + if (!gl_info->supported[EXT_TEXTURE3D]) + { + WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); + return WINED3DERR_INVALIDCALL; + } + + if (desc->usage & WINED3DUSAGE_DYNAMIC && (wined3d_resource_access_is_managed(desc->access) + || desc->usage & WINED3DUSAGE_SCRATCH)) + { + WARN("Attempted to create a DYNAMIC texture with access %s.\n", + wined3d_debug_resource_access(desc->access)); + return WINED3DERR_INVALIDCALL; + } + + if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) + { + if (!is_power_of_two(desc->width) || !is_power_of_two(desc->height) || !is_power_of_two(desc->depth)) + { + if (desc->usage & WINED3DUSAGE_SCRATCH) + { + WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n"); + } + else + { + WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n", + desc->width, desc->height, desc->depth); + return WINED3DERR_INVALIDCALL; + } + } + } + + if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, level_count, desc, + flags, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); + return hr; + } + + texture->pow2_matrix[0] = 1.0f; + texture->pow2_matrix[5] = 1.0f; + texture->pow2_matrix[10] = 1.0f; + texture->pow2_matrix[15] = 1.0f; + texture->target = GL_TEXTURE_3D; + + if (wined3d_texture_use_pbo(texture, gl_info)) + { + wined3d_resource_free_sysmem(&texture->resource); + texture->resource.map_binding = WINED3D_LOCATION_BUFFER; + } + + /* Generate all the sub resources. */ + for (i = 0; i < texture->level_count; ++i) + { + struct wined3d_texture_sub_resource *sub_resource; + + sub_resource = &texture->sub_resources[i]; + sub_resource->locations = WINED3D_LOCATION_DISCARDED; + + if (FAILED(hr = device_parent->ops->volume_created(device_parent, + texture, i, &sub_resource->parent, &sub_resource->parent_ops))) + { + WARN("Failed to create volume parent, hr %#x.\n", hr); + sub_resource->parent = NULL; + wined3d_texture_cleanup_sync(texture); + return hr; + } + + TRACE("parent %p, parent_ops %p.\n", parent, parent_ops); + + TRACE("Created volume level %u.\n", i); + } + + return WINED3D_OK; +} + HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) @@ -3119,8 +3294,19 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || src_texture->sub_resources[src_sub_resource_idx].map_count) { +#if !defined(STAGING_CSMT) WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); return WINEDDERR_SURFACEBUSY; +#else /* STAGING_CSMT */ + struct wined3d_device *device = dst_texture->resource.device; + device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count + || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) + { + WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); + return WINEDDERR_SURFACEBUSY; + } +#endif /* STAGING_CSMT */ } if ((src_format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) @@ -3151,7 +3337,7 @@ HRESULT CDECL wined3d_texture_get_overlay_position(const struct wined3d_texture } overlay = &texture->overlay_info[sub_resource_idx]; - if (!overlay->dst_texture) + if (!overlay->dst) { TRACE("Overlay not visible.\n"); *x = 0; @@ -3194,8 +3380,9 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const RECT *dst_rect, DWORD flags) { + struct wined3d_texture_sub_resource *sub_resource, *dst_sub_resource; + struct wined3d_surface *surface, *dst_surface; struct wined3d_overlay_info *overlay; - unsigned int level, dst_level; TRACE("texture %p, sub_resource_idx %u, src_rect %s, dst_texture %p, " "dst_sub_resource_idx %u, dst_rect %s, flags %#x.\n", @@ -3203,14 +3390,14 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), flags); if (!(texture->resource.usage & WINED3DUSAGE_OVERLAY) || texture->resource.type != WINED3D_RTYPE_TEXTURE_2D - || sub_resource_idx >= texture->level_count * texture->layer_count) + || !(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx))) { WARN("Invalid sub-resource specified.\n"); return WINEDDERR_NOTAOVERLAYSURFACE; } if (!dst_texture || dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D - || dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count) + || !(dst_sub_resource = wined3d_texture_get_sub_resource(dst_texture, dst_sub_resource_idx))) { WARN("Invalid destination sub-resource specified.\n"); return WINED3DERR_INVALIDCALL; @@ -3218,35 +3405,33 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un overlay = &texture->overlay_info[sub_resource_idx]; - level = sub_resource_idx % texture->level_count; + surface = sub_resource->u.surface; if (src_rect) overlay->src_rect = *src_rect; else SetRect(&overlay->src_rect, 0, 0, - wined3d_texture_get_level_width(texture, level), - wined3d_texture_get_level_height(texture, level)); + wined3d_texture_get_level_width(texture, surface->texture_level), + wined3d_texture_get_level_height(texture, surface->texture_level)); - dst_level = dst_sub_resource_idx % dst_texture->level_count; + dst_surface = dst_sub_resource->u.surface; if (dst_rect) overlay->dst_rect = *dst_rect; else SetRect(&overlay->dst_rect, 0, 0, - wined3d_texture_get_level_width(dst_texture, dst_level), - wined3d_texture_get_level_height(dst_texture, dst_level)); + wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level), + wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level)); - if (overlay->dst_texture && (overlay->dst_texture != dst_texture - || overlay->dst_sub_resource_idx != dst_sub_resource_idx || flags & WINEDDOVER_HIDE)) + if (overlay->dst && (overlay->dst != dst_surface || flags & WINEDDOVER_HIDE)) { - overlay->dst_texture = NULL; + overlay->dst = NULL; list_remove(&overlay->entry); } if (flags & WINEDDOVER_SHOW) { - if (overlay->dst_texture != dst_texture || overlay->dst_sub_resource_idx != dst_sub_resource_idx) + if (overlay->dst != dst_surface) { - overlay->dst_texture = dst_texture; - overlay->dst_sub_resource_idx = dst_sub_resource_idx; + overlay->dst = dst_surface; list_add_tail(&texture->overlay_info[dst_sub_resource_idx].overlays, &overlay->entry); } } @@ -3255,7 +3440,7 @@ HRESULT CDECL wined3d_texture_update_overlay(struct wined3d_texture *texture, un /* Tests show that the rectangles are erased on hide. */ SetRectEmpty(&overlay->src_rect); SetRectEmpty(&overlay->dst_rect); - overlay->dst_texture = NULL; + overlay->dst = NULL; } return WINED3D_OK; @@ -3327,7 +3512,6 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct UINT layer_count, UINT level_count, DWORD flags, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture) { - const struct wined3d_texture_ops *texture_ops; struct wined3d_texture *object; HRESULT hr; @@ -3374,28 +3558,31 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct } } + if (!(object = heap_alloc_zero(FIELD_OFFSET(struct wined3d_texture, + sub_resources[level_count * layer_count])))) + return E_OUTOFMEMORY; + switch (desc->resource_type) { case WINED3D_RTYPE_TEXTURE_1D: - texture_ops = &texture1d_ops; + hr = texture1d_init(object, desc, layer_count, level_count, device, parent, parent_ops); break; + case WINED3D_RTYPE_TEXTURE_2D: - texture_ops = &texture2d_ops; + hr = texture_init(object, desc, layer_count, level_count, flags, device, parent, parent_ops); break; + case WINED3D_RTYPE_TEXTURE_3D: - texture_ops = &texture3d_ops; + hr = volumetexture_init(object, desc, layer_count, level_count, flags, device, parent, parent_ops); break; + default: ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc->resource_type)); - return WINED3DERR_INVALIDCALL; + hr = WINED3DERR_INVALIDCALL; + break; } - if (!(object = heap_alloc_zero(FIELD_OFFSET(struct wined3d_texture, - sub_resources[level_count * layer_count])))) - return E_OUTOFMEMORY; - - if (FAILED(hr = wined3d_texture_init(object, desc, layer_count, - level_count, flags, device, parent, parent_ops, texture_ops))) + if (FAILED(hr)) { WARN("Failed to initialize texture, returning %#x.\n", hr); heap_free(object); @@ -3423,7 +3610,7 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct for (i = 0; i < sub_count; ++i) { wined3d_device_update_sub_resource(device, &object->resource, - i, NULL, data[i].data, data[i].row_pitch, data[i].slice_pitch, 0); + i, NULL, data[i].data, data[i].row_pitch, data[i].slice_pitch); } } @@ -3437,7 +3624,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i { struct wined3d_device *device = texture->resource.device; struct wined3d_texture_sub_resource *sub_resource; - struct wined3d_dc_info *dc_info; + struct wined3d_surface *surface; TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); @@ -3457,25 +3644,25 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i return WINED3DERR_INVALIDCALL; } + surface = sub_resource->u.surface; + if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) return WINED3DERR_INVALIDCALL; - if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc) + if (!surface->dc) { - struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx}; - - wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx); + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc) - return WINED3DERR_INVALIDCALL; } + if (!surface->dc) + return WINED3DERR_INVALIDCALL; if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) texture->flags |= WINED3D_TEXTURE_DC_IN_USE; ++texture->resource.map_count; ++sub_resource->map_count; - *dc = dc_info[sub_resource_idx].dc; + *dc = surface->dc; TRACE("Returning dc %p.\n", *dc); return WINED3D_OK; @@ -3485,7 +3672,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign { struct wined3d_device *device = texture->resource.device; struct wined3d_texture_sub_resource *sub_resource; - struct wined3d_dc_info *dc_info; + struct wined3d_surface *surface; TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); @@ -3498,21 +3685,20 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign return WINED3DERR_INVALIDCALL; } + surface = sub_resource->u.surface; + if (!(texture->flags & (WINED3D_TEXTURE_GET_DC_LENIENT | WINED3D_TEXTURE_DC_IN_USE))) return WINED3DERR_INVALIDCALL; - if (!(dc_info = texture->dc_info) || dc_info[sub_resource_idx].dc != dc) + if (surface->dc != dc) { - WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n", - dc, dc_info ? dc_info[sub_resource_idx].dc : NULL); + WARN("Application tries to release invalid DC %p, surface DC is %p.\n", dc, surface->dc); return WINED3DERR_INVALIDCALL; } if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) { - struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx}; - - wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx); + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -3524,49 +3710,3 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign return WINED3D_OK; } - -void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture, - unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) -{ - unsigned int src_row_pitch, src_slice_pitch; - unsigned int update_w, update_h, update_d; - unsigned int src_level, dst_level; - struct wined3d_context *context; - struct wined3d_bo_address data; - - TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " - "src_texture %p, src_sub_resource_idx %u, src_box %s.\n", - dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z, - src_texture, src_sub_resource_idx, debug_box(src_box)); - - context = context_acquire(dst_texture->resource.device, NULL, 0); - - /* Only load the sub-resource for partial updates. For newly allocated - * textures the texture wouldn't be the current location, and we'd upload - * zeroes just to overwrite them again. */ - update_w = src_box->right - src_box->left; - update_h = src_box->bottom - src_box->top; - update_d = src_box->back - src_box->front; - dst_level = dst_sub_resource_idx % dst_texture->level_count; - if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level) - && update_h == wined3d_texture_get_level_height(dst_texture, dst_level) - && update_d == wined3d_texture_get_level_depth(dst_texture, dst_level)) - wined3d_texture_prepare_texture(dst_texture, context, FALSE); - else - wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE); - - src_level = src_sub_resource_idx % src_texture->level_count; - wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data, - src_texture->sub_resources[src_sub_resource_idx].locations); - wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch); - - wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format, - src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, FALSE); - - context_release(context); - - wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); -} diff --git a/dll/directx/wine/wined3d/utils.c b/dll/directx/wine/wined3d/utils.c index 91960389587..b48293eabb3 100644 --- a/dll/directx/wine/wined3d/utils.c +++ b/dll/directx/wine/wined3d/utils.c @@ -122,6 +122,7 @@ static const struct wined3d_format_channels formats[] = /* Bump mapping stuff */ {WINED3DFMT_R5G5_SNORM_L6_UNORM, 5, 5, 0, 0, 0, 5, 0, 0, 2, 0, 0}, {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, 8, 8, 0, 0, 0, 8, 0, 0, 4, 0, 0}, + {WINED3DFMT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0}, {WINED3DFMT_R10G11B11_SNORM, 10, 11, 11, 0, 0, 10, 21, 0, 4, 0, 0}, {WINED3DFMT_R10G10B10X2_UINT, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0}, {WINED3DFMT_R10G10B10X2_SNORM, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0}, @@ -132,6 +133,8 @@ static const struct wined3d_format_channels formats[] = {WINED3DFMT_S1_UINT_D15_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 15, 1}, {WINED3DFMT_X8D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 0}, {WINED3DFMT_S4X4_UINT_D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 4}, + {WINED3DFMT_D16_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0}, + {WINED3DFMT_D32_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0}, {WINED3DFMT_S8_UINT_D24_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8}, /* Vendor-specific formats */ {WINED3DFMT_ATI1N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, @@ -892,9 +895,45 @@ static BOOL color_in_range(const struct wined3d_color_key *color_key, DWORD colo && color <= color_key->color_space_high_value; } +static void convert_p8_uint_b8g8r8a8_unorm(const BYTE *src, unsigned int src_pitch, + BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) +{ + const BYTE *src_row; + unsigned int x, y; + DWORD *dst_row; + + if (!palette) + { + /* FIXME: This should probably use the system palette. */ + FIXME("P8 surface loaded without a palette.\n"); + + for (y = 0; y < height; ++y) + { + memset(&dst[dst_pitch * y], 0, width * 4); + } + + return; + } + + for (y = 0; y < height; ++y) + { + src_row = &src[src_pitch * y]; + dst_row = (DWORD *)&dst[dst_pitch * y]; + for (x = 0; x < width; ++x) + { + BYTE src_color = src_row[x]; + dst_row[x] = 0xff000000 + | (palette->colors[src_color].rgbRed << 16) + | (palette->colors[src_color].rgbGreen << 8) + | palette->colors[src_color].rgbBlue; + } + } +} + static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, - const struct wined3d_color_key *color_key) + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) { const WORD *src_row; unsigned int x, y; @@ -917,7 +956,7 @@ static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsig static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, - const struct wined3d_color_key *color_key) + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) { const WORD *src_row; unsigned int x, y; @@ -940,7 +979,7 @@ static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, uns static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, - const struct wined3d_color_key *color_key) + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) { const BYTE *src_row; unsigned int x, y; @@ -961,7 +1000,7 @@ static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsig static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, - const struct wined3d_color_key *color_key) + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) { const DWORD *src_row; unsigned int x, y; @@ -984,7 +1023,7 @@ static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, uns static void convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height, - const struct wined3d_color_key *color_key) + const struct wined3d_palette *palette, const struct wined3d_color_key *color_key) { const DWORD *src_row; unsigned int x, y; @@ -1023,6 +1062,10 @@ const struct wined3d_color_key_conversion * wined3d_format_get_color_key_convers {WINED3DFMT_B8G8R8X8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key }}, {WINED3DFMT_B8G8R8A8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key }}, }; + static const struct wined3d_color_key_conversion convert_p8 = + { + WINED3DFMT_B8G8R8A8_UNORM, convert_p8_uint_b8g8r8a8_unorm + }; if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)) { @@ -1035,6 +1078,13 @@ const struct wined3d_color_key_conversion * wined3d_format_get_color_key_convers FIXME("Color-keying not supported with format %s.\n", debug_d3dformat(format->id)); } + /* FIXME: This should check if the blitter backend can do P8 conversion, + * instead of checking for ARB_fragment_program. */ + if (format->id == WINED3DFMT_P8_UINT + && !(texture->resource.device->adapter->gl_info.supported[ARB_FRAGMENT_PROGRAM] + && texture->swapchain && texture == texture->swapchain->front_buffer)) + return &convert_p8; + return NULL; } @@ -1634,6 +1684,10 @@ static const struct wined3d_format_texture_info format_texture_info[] = GL_RGBA_INTEGER, GL_INT, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET, EXT_TEXTURE_INTEGER, NULL}, + {WINED3DFMT_R24_UNORM_X8_TYPELESS, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8, 0, + WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE, NULL}, /* Vendor-specific formats */ {WINED3DFMT_ATI1N, GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_RED_RGTC1, 0, GL_RED, GL_UNSIGNED_BYTE, 0, @@ -2753,7 +2807,7 @@ static void query_internal_format(struct wined3d_adapter *adapter, struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info, struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format) { - GLint count, multisample_types[8]; + GLint count, multisample_types[MAX_MULTISAMPLE_TYPES]; unsigned int i, max_log2; GLenum target; @@ -2832,9 +2886,7 @@ static void query_internal_format(struct wined3d_adapter *adapter, count = 0; GL_EXTCALL(glGetInternalformativ(target, format->glInternal, GL_NUM_SAMPLE_COUNTS, 1, &count)); - if (count > ARRAY_SIZE(multisample_types)) - FIXME("Unexpectedly high number of multisample types %d.\n", count); - count = min(count, ARRAY_SIZE(multisample_types)); + count = min(count, MAX_MULTISAMPLE_TYPES); GL_EXTCALL(glGetInternalformativ(target, format->glInternal, GL_SAMPLES, count, multisample_types)); checkGLcall("query sample counts"); @@ -3222,8 +3274,8 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE); } - if (!gl_info->supported[APPLE_YCBCR_422] && (gl_info->supported[ARB_FRAGMENT_PROGRAM] - || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER]))) + if (!gl_info->supported[APPLE_YCBCR_422] && gl_info->supported[ARB_FRAGMENT_PROGRAM] + && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) { idx = get_format_idx(WINED3DFMT_YUY2); gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2); @@ -3232,7 +3284,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY); } else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM] - && (!gl_info->supported[ARB_FRAGMENT_SHADER] || !gl_info->supported[ARB_VERTEX_SHADER]))) + || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])) { idx = get_format_idx(WINED3DFMT_YUY2); gl_info->formats[idx].glInternal = 0; @@ -3241,8 +3293,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ gl_info->formats[idx].glInternal = 0; } - if (gl_info->supported[ARB_FRAGMENT_PROGRAM] - || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER])) + if (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) { idx = get_format_idx(WINED3DFMT_YV12); format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_HEIGHT_SCALE); @@ -3291,7 +3342,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE); } - if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER]) + if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) { idx = get_format_idx(WINED3DFMT_P8_UINT); gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8); @@ -4445,6 +4496,7 @@ const char *debug_d3drenderstate(enum wined3d_render_state state) D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA); D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA); D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA); + D3DSTATE_TO_STR(WINED3D_RS_DEPTHCLIP); #undef D3DSTATE_TO_STR default: FIXME("Unrecognized %u render state!\n", state); @@ -4663,8 +4715,8 @@ const char *debug_d3dstate(DWORD state) return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0)); if (STATE_IS_MATERIAL(state)) return "STATE_MATERIAL"; - if (STATE_IS_RASTERIZER(state)) - return "STATE_RASTERIZER"; + if (STATE_IS_FRONTFACE(state)) + return "STATE_FRONTFACE"; if (STATE_IS_POINTSPRITECOORDORIGIN(state)) return "STATE_POINTSPRITECOORDORIGIN"; if (STATE_IS_BASEVERTEXINDEX(state)) @@ -4876,10 +4928,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w if (context->last_was_rhw) { /* Transform D3D RHW coordinates to OpenGL clip coordinates. */ - float x = state->viewports[0].x; - float y = state->viewports[0].y; - float w = state->viewports[0].width; - float h = state->viewports[0].height; + float x = state->viewport.x; + float y = state->viewport.y; + float w = state->viewport.width; + float h = state->viewport.height; float x_scale = 2.0f / w; float x_offset = (center_offset - (2.0f * x) - w) / w; float y_scale = flip ? 2.0f / h : 2.0f / -h; @@ -4903,10 +4955,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w else { float y_scale = flip ? -1.0f : 1.0f; - float x_offset = center_offset / state->viewports[0].width; + float x_offset = center_offset / state->viewport.width; float y_offset = flip - ? center_offset / state->viewports[0].height - : -center_offset / state->viewports[0].height; + ? center_offset / state->viewport.height + : -center_offset / state->viewport.height; float z_scale = clip_control ? 1.0f : 2.0f; float z_offset = clip_control ? 0.0f : -1.0f; const struct wined3d_matrix projection = @@ -5106,10 +5158,9 @@ void get_pointsize(const struct wined3d_context *context, const struct wined3d_s b.d = state->render_states[WINED3D_RS_POINTSCALE_B]; c.d = state->render_states[WINED3D_RS_POINTSCALE_C]; - /* Always use first viewport, this path does not apply to d3d10/11 multiple viewports case. */ if (state->render_states[WINED3D_RS_POINTSCALEENABLE]) { - float scale_factor = state->viewports[0].height * state->viewports[0].height; + float scale_factor = state->viewport.height * state->viewport.height; out_att[0] = a.f / scale_factor; out_att[1] = b.f / scale_factor; @@ -5746,9 +5797,9 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED; settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED; settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY; - settings->op[i].tmp_dst = 0; + settings->op[i].dst = resultreg; settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D; - settings->op[i].projected = WINED3D_PROJECTION_NONE; + settings->op[i].projected = proj_none; i++; break; } @@ -5872,15 +5923,15 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d { ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS]; if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3)) - settings->op[i].projected = WINED3D_PROJECTION_COUNT3; + settings->op[i].projected = proj_count3; else if (ttff & WINED3D_TTFF_PROJECTED) - settings->op[i].projected = WINED3D_PROJECTION_COUNT4; + settings->op[i].projected = proj_count4; else - settings->op[i].projected = WINED3D_PROJECTION_NONE; + settings->op[i].projected = proj_none; } else { - settings->op[i].projected = WINED3D_PROJECTION_NONE; + settings->op[i].projected = proj_none; } settings->op[i].cop = cop; @@ -5891,7 +5942,11 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d settings->op[i].aarg0 = aarg0; settings->op[i].aarg1 = aarg1; settings->op[i].aarg2 = aarg2; - settings->op[i].tmp_dst = state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP; + + if (state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP) + settings->op[i].dst = tempreg; + else + settings->op[i].dst = resultreg; } /* Clear unsupported stages */ @@ -6038,7 +6093,27 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st { switch (texture->target) { + case GL_TEXTURE_1D: + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + { + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) + { + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_1D); + checkGLcall("glEnable(GL_TEXTURE_1D)"); + break; case GL_TEXTURE_2D: + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable(GL_TEXTURE_1D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); checkGLcall("glDisable(GL_TEXTURE_3D)"); if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) @@ -6055,6 +6130,8 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st checkGLcall("glEnable(GL_TEXTURE_2D)"); break; case GL_TEXTURE_RECTANGLE_ARB: + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable(GL_TEXTURE_1D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); @@ -6078,12 +6155,16 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); } + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable(GL_TEXTURE_1D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D); checkGLcall("glEnable(GL_TEXTURE_3D)"); break; case GL_TEXTURE_CUBE_MAP_ARB: + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable(GL_TEXTURE_1D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); @@ -6100,6 +6181,8 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st } else { + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable(GL_TEXTURE_1D)"); gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D); checkGLcall("glEnable(GL_TEXTURE_2D)"); gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); diff --git a/dll/directx/wine/wined3d/view.c b/dll/directx/wine/wined3d/view.c index 5edaef8b352..bed39dbc5fc 100644 --- a/dll/directx/wine/wined3d/view.c +++ b/dll/directx/wine/wined3d/view.c @@ -48,6 +48,11 @@ static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info, {GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_RECTANGLE}, {GL_TEXTURE_3D, 0, GL_TEXTURE_3D}, + {GL_TEXTURE_1D, 0, GL_TEXTURE_1D}, + {GL_TEXTURE_1D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY}, + {GL_TEXTURE_1D_ARRAY, 0, GL_TEXTURE_1D}, + {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY}, + {GL_TEXTURE_2D, 0, GL_TEXTURE_2D}, {GL_TEXTURE_2D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY}, {GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_2D}, @@ -59,11 +64,6 @@ static GLenum get_texture_view_target(const struct wined3d_gl_info *gl_info, {GL_TEXTURE_2D_MULTISAMPLE, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY}, {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0, GL_TEXTURE_2D_MULTISAMPLE}, {GL_TEXTURE_2D_MULTISAMPLE_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY}, - - {GL_TEXTURE_1D, 0, GL_TEXTURE_1D}, - {GL_TEXTURE_1D, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY}, - {GL_TEXTURE_1D_ARRAY, 0, GL_TEXTURE_1D}, - {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY}, }; unsigned int i; @@ -750,8 +750,10 @@ static void wined3d_shader_resource_view_cs_init(void *object) debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id)); } } +#if defined(STAGING_CSMT) wined3d_resource_release(resource); +#endif /* STAGING_CSMT */ } static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view, @@ -768,7 +770,9 @@ static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_ wined3d_resource_incref(view->resource = resource); +#if defined(STAGING_CSMT) wined3d_resource_acquire(resource); +#endif /* STAGING_CSMT */ wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_cs_init, view); return WINED3D_OK; @@ -1121,8 +1125,10 @@ static void wined3d_unordered_access_view_cs_init(void *object) desc, texture, view->format); } } +#if defined(STAGING_CSMT) wined3d_resource_release(resource); +#endif /* STAGING_CSMT */ } static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view, @@ -1139,7 +1145,9 @@ static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_acces wined3d_resource_incref(view->resource = resource); +#if defined(STAGING_CSMT) wined3d_resource_acquire(resource); +#endif /* STAGING_CSMT */ wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_cs_init, view); return WINED3D_OK; diff --git a/dll/directx/wine/wined3d/wined3d.spec b/dll/directx/wine/wined3d/wined3d.spec index 449d98712e4..3022e20edbe 100644 --- a/dll/directx/wine/wined3d/wined3d.spec +++ b/dll/directx/wine/wined3d/wined3d.spec @@ -40,7 +40,7 @@ @ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr long ptr float long) @ cdecl wined3d_device_clear_unordered_access_view_uint(ptr ptr ptr) @ cdecl wined3d_device_copy_resource(ptr ptr ptr) -@ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr long) +@ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr) @ cdecl wined3d_device_copy_uav_counter(ptr ptr long ptr) @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr) @ cdecl wined3d_device_decref(ptr) @@ -86,7 +86,6 @@ @ cdecl wined3d_device_get_light(ptr long ptr) @ cdecl wined3d_device_get_light_enable(ptr long ptr) @ cdecl wined3d_device_get_material(ptr ptr) -@ cdecl wined3d_device_get_max_frame_latency(ptr) @ cdecl wined3d_device_get_npatch_mode(ptr) @ cdecl wined3d_device_get_pixel_shader(ptr) @ cdecl wined3d_device_get_predication(ptr ptr) @@ -102,7 +101,7 @@ @ cdecl wined3d_device_get_render_state(ptr long) @ cdecl wined3d_device_get_rendertarget_view(ptr long) @ cdecl wined3d_device_get_sampler_state(ptr long long) -@ cdecl wined3d_device_get_scissor_rects(ptr ptr ptr) +@ cdecl wined3d_device_get_scissor_rect(ptr ptr) @ cdecl wined3d_device_get_software_vertex_processing(ptr) @ cdecl wined3d_device_get_stream_output(ptr long ptr) @ cdecl wined3d_device_get_stream_source(ptr long ptr ptr ptr) @@ -115,7 +114,7 @@ @ cdecl wined3d_device_get_unordered_access_view(ptr long) @ cdecl wined3d_device_get_vertex_declaration(ptr) @ cdecl wined3d_device_get_vertex_shader(ptr) -@ cdecl wined3d_device_get_viewports(ptr ptr ptr) +@ cdecl wined3d_device_get_viewport(ptr ptr) @ cdecl wined3d_device_get_vs_cb(ptr long) @ cdecl wined3d_device_get_vs_consts_b(ptr long long ptr) @ cdecl wined3d_device_get_vs_consts_f(ptr long long ptr) @@ -162,7 +161,6 @@ @ cdecl wined3d_device_set_light(ptr long ptr) @ cdecl wined3d_device_set_light_enable(ptr long long) @ cdecl wined3d_device_set_material(ptr ptr) -@ cdecl wined3d_device_set_max_frame_latency(ptr long) @ cdecl wined3d_device_set_multithreaded(ptr) @ cdecl wined3d_device_set_npatch_mode(ptr float) @ cdecl wined3d_device_set_pixel_shader(ptr ptr) @@ -178,7 +176,7 @@ @ cdecl wined3d_device_set_render_state(ptr long long) @ cdecl wined3d_device_set_rendertarget_view(ptr long ptr long) @ cdecl wined3d_device_set_sampler_state(ptr long long long) -@ cdecl wined3d_device_set_scissor_rects(ptr long ptr) +@ cdecl wined3d_device_set_scissor_rect(ptr ptr) @ cdecl wined3d_device_set_software_vertex_processing(ptr long) @ cdecl wined3d_device_set_stream_output(ptr long ptr long) @ cdecl wined3d_device_set_stream_source(ptr long ptr long long) @@ -189,7 +187,7 @@ @ cdecl wined3d_device_set_unordered_access_view(ptr long ptr long) @ cdecl wined3d_device_set_vertex_declaration(ptr ptr) @ cdecl wined3d_device_set_vertex_shader(ptr ptr) -@ cdecl wined3d_device_set_viewports(ptr long ptr) +@ cdecl wined3d_device_set_viewport(ptr ptr) @ cdecl wined3d_device_set_vs_cb(ptr long ptr) @ cdecl wined3d_device_set_vs_consts_b(ptr long long ptr) @ cdecl wined3d_device_set_vs_consts_f(ptr long long ptr) @@ -200,7 +198,7 @@ @ cdecl wined3d_device_show_cursor(ptr long) @ cdecl wined3d_device_uninit_3d(ptr) @ cdecl wined3d_device_uninit_gdi(ptr) -@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long long) +@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long) @ cdecl wined3d_device_update_texture(ptr ptr ptr) @ cdecl wined3d_device_validate_device(ptr ptr) @@ -274,6 +272,8 @@ @ cdecl wined3d_stateblock_decref(ptr) @ cdecl wined3d_stateblock_incref(ptr) +@ cdecl wined3d_strictdrawing_set(long) + @ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr) @ cdecl wined3d_swapchain_decref(ptr) @ cdecl wined3d_swapchain_get_back_buffer(ptr long) diff --git a/dll/directx/wine/wined3d/wined3d_gl.h b/dll/directx/wine/wined3d/wined3d_gl.h index 14f8a497344..87283c850e1 100644 --- a/dll/directx/wine/wined3d/wined3d_gl.h +++ b/dll/directx/wine/wined3d/wined3d_gl.h @@ -89,7 +89,6 @@ enum wined3d_gl_extension ARB_POINT_PARAMETERS, ARB_POINT_SPRITE, ARB_PROVOKING_VERTEX, - ARB_SAMPLE_SHADING, ARB_SAMPLER_OBJECTS, ARB_SEAMLESS_CUBE_MAP, ARB_SHADER_ATOMIC_COUNTERS, @@ -97,7 +96,6 @@ enum wined3d_gl_extension ARB_SHADER_IMAGE_LOAD_STORE, ARB_SHADER_IMAGE_SIZE, ARB_SHADER_STORAGE_BUFFER_OBJECT, - ARB_SHADER_TEXTURE_IMAGE_SAMPLES, ARB_SHADER_TEXTURE_LOD, ARB_SHADING_LANGUAGE_100, ARB_SHADING_LANGUAGE_420PACK, @@ -136,6 +134,7 @@ enum wined3d_gl_extension ARB_TRANSFORM_FEEDBACK3, ARB_UNIFORM_BUFFER_OBJECT, ARB_VERTEX_ARRAY_BGRA, + ARB_VERTEX_BLEND, ARB_VERTEX_BUFFER_OBJECT, ARB_VERTEX_PROGRAM, ARB_VERTEX_SHADER, diff --git a/dll/directx/wine/wined3d/wined3d_main.c b/dll/directx/wine/wined3d/wined3d_main.c index 604e6e4ed90..28e6fe60cfe 100644 --- a/dll/directx/wine/wined3d/wined3d_main.c +++ b/dll/directx/wine/wined3d/wined3d_main.c @@ -74,7 +74,7 @@ struct wined3d_settings wined3d_settings = { TRUE, /* Multithreaded CS by default. */ FALSE, /* explicit_gl_version */ - MAKEDWORD_VERSION(4, 4), /* Default to OpenGL 4.4 */ + MAKEDWORD_VERSION(1, 0), /* Default to legacy OpenGL */ TRUE, /* Use of GLSL enabled by default */ ORM_FBO, /* Use FBOs to do offscreen rendering */ PCI_VENDOR_NONE,/* PCI Vendor ID */ @@ -83,6 +83,7 @@ struct wined3d_settings wined3d_settings = NULL, /* No wine logo by default */ TRUE, /* Prefer multisample textures to multisample renderbuffers. */ ~0u, /* Don't force a specific sample count by default. */ + FALSE, /* No strict draw ordering. */ FALSE, /* Don't range check relative addressing indices in float constants. */ ~0U, /* No VS shader model limit by default. */ ~0U, /* No HS shader model limit by default. */ @@ -289,6 +290,13 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) if (!get_config_key_dword(hkey, appkey, "SampleCount", &wined3d_settings.sample_count)) ERR_(winediag)("Forcing sample count to %u. This may not be compatible with all applications.\n", wined3d_settings.sample_count); + if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size) + && !strcmp(buffer,"enabled")) + { + ERR_(winediag)("\"StrictDrawOrdering\" is deprecated, please use \"csmt\" instead.\n"); + TRACE("Enforcing strict draw ordering.\n"); + wined3d_settings.strict_draw_ordering = TRUE; + } if (!get_config_key(hkey, appkey, "CheckFloatConstants", buffer, size) && !strcmp(buffer, "enabled")) { @@ -508,6 +516,11 @@ void wined3d_unregister_window(HWND window) wined3d_wndproc_mutex_unlock(); } +void CDECL wined3d_strictdrawing_set(int value) +{ + wined3d_settings.strict_draw_ordering = value; +} + /* At process attach */ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) { diff --git a/dll/directx/wine/wined3d/wined3d_private.h b/dll/directx/wine/wined3d/wined3d_private.h index 3cf67482377..b127fa71faa 100644 --- a/dll/directx/wine/wined3d/wined3d_private.h +++ b/dll/directx/wine/wined3d/wined3d_private.h @@ -277,6 +277,7 @@ static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup #define MAX_TGSM_REGISTERS 8192 #define MAX_VERTEX_BLENDS 4 #define MAX_VERTEX_INDEX_BLENDS 9 +#define MAX_MULTISAMPLE_TYPES 8 #define MAX_RENDER_TARGETS 8 struct min_lookup @@ -401,6 +402,7 @@ struct wined3d_settings char *logo; unsigned int multisample_textures; unsigned int sample_count; + BOOL strict_draw_ordering; BOOL check_float_constants; unsigned int max_sm_vs; unsigned int max_sm_hs; @@ -504,7 +506,6 @@ enum wined3d_shader_register_type WINED3DSPR_GSINSTID, WINED3DSPR_DEPTHOUTGE, WINED3DSPR_DEPTHOUTLE, - WINED3DSPR_RASTERIZER, }; enum wined3d_data_type @@ -626,14 +627,6 @@ enum wined3d_tessellator_partitioning #define WINED3DSI_SAMPLE_INFO_UINT 0x1 #define WINED3DSI_SAMPLER_COMPARISON_MODE 0x1 -#define WINED3DSI_PRECISE_X 0x100 -#define WINED3DSI_PRECISE_Y 0x200 -#define WINED3DSI_PRECISE_Z 0x400 -#define WINED3DSI_PRECISE_W 0x800 -#define WINED3DSI_PRECISE_XYZW (WINED3DSI_PRECISE_X | WINED3DSI_PRECISE_Y \ - | WINED3DSI_PRECISE_Z | WINED3DSI_PRECISE_W) -#define WINED3DSI_PRECISE_SHIFT 8 - enum wined3d_shader_rel_op { WINED3D_SHADER_REL_OP_GT = 1, @@ -945,7 +938,6 @@ enum wined3d_shader_type WINED3D_SHADER_TYPE_COMPUTE = WINED3D_SHADER_TYPE_GRAPHICS_COUNT, WINED3D_SHADER_TYPE_COUNT, - WINED3D_SHADER_TYPE_INVALID = WINED3D_SHADER_TYPE_COUNT, }; struct wined3d_shader_version @@ -1046,9 +1038,7 @@ struct wined3d_shader_reg_maps DWORD point_size : 1; DWORD vocp : 1; DWORD input_rel_addressing : 1; - DWORD viewport_array : 1; - DWORD sample_mask : 1; - DWORD padding : 14; + DWORD padding : 16; DWORD rt_mask; /* Used render targets, 32 max. */ @@ -1284,9 +1274,6 @@ struct wined3d_shader_frontend extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN; extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN; -enum wined3d_shader_type wined3d_get_sm4_shader_type(const DWORD *byte_code, - size_t byte_code_size) DECLSPEC_HIDDEN; - typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *); #define WINED3D_SHADER_CAP_VS_CLIPPING 0x00000001 @@ -1322,11 +1309,10 @@ enum wined3d_gl_resource_type WINED3D_GL_RES_TYPE_COUNT = 7, }; -enum wined3d_vertex_processing_mode -{ - WINED3D_VP_MODE_FF, - WINED3D_VP_MODE_SHADER, - WINED3D_VP_MODE_NONE, +enum vertexprocessing_mode { + fixedfunction, + vertexshader, + pretransformed }; #define WINED3D_CONST_NUM_UNUSED ~0U @@ -1361,7 +1347,7 @@ enum wined3d_shader_tex_types struct ps_compile_args { struct color_fixup_desc color_fixup[MAX_FRAGMENT_SAMPLERS]; - enum wined3d_vertex_processing_mode vp_mode; + enum vertexprocessing_mode vp_mode; enum wined3d_ffp_ps_fog_mode fog; WORD tex_transform; /* ps 1.0-1.3, 4 textures */ WORD tex_types; /* ps 1.0 - 1.4, 6 textures */ @@ -1414,7 +1400,6 @@ struct ds_compile_args struct gs_compile_args { unsigned int output_count; - enum wined3d_primitive_type primitive_type; DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE]; }; @@ -1648,10 +1633,10 @@ enum wined3d_pipeline #define STATE_MATERIAL (STATE_CLIPPLANE(MAX_CLIP_DISTANCES)) #define STATE_IS_MATERIAL(a) ((a) == STATE_MATERIAL) -#define STATE_RASTERIZER (STATE_MATERIAL + 1) -#define STATE_IS_RASTERIZER(a) ((a) == STATE_RASTERIZER) +#define STATE_FRONTFACE (STATE_MATERIAL + 1) +#define STATE_IS_FRONTFACE(a) ((a) == STATE_FRONTFACE) -#define STATE_POINTSPRITECOORDORIGIN (STATE_RASTERIZER + 1) +#define STATE_POINTSPRITECOORDORIGIN (STATE_FRONTFACE + 1) #define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN) #define STATE_BASEVERTEXINDEX (STATE_POINTSPRITECOORDORIGIN + 1) @@ -1907,7 +1892,7 @@ struct wined3d_context DWORD last_was_vshader : 1; DWORD last_was_normal : 1; DWORD namedArraysLoaded : 1; - DWORD last_was_ffp_blit : 1; + DWORD numberedArraysLoaded : 1; DWORD last_was_blit : 1; DWORD last_was_ckey : 1; DWORD fog_coord : 1; @@ -1916,7 +1901,6 @@ struct wined3d_context DWORD current : 1; DWORD destroyed : 1; DWORD valid : 1; - DWORD texShaderBumpMap : 8; /* MAX_TEXTURES, 8 */ DWORD lastWasPow2Texture : 8; /* MAX_TEXTURES, 8 */ DWORD fixed_function_usage_map : 8; /* MAX_TEXTURES, 8 */ @@ -1925,7 +1909,6 @@ struct wined3d_context DWORD rebind_fbo : 1; DWORD needs_set : 1; DWORD hdc_is_private : 1; - DWORD hdc_has_format : 1; /* only meaningful if hdc_is_private */ DWORD update_shader_resource_bindings : 1; DWORD update_compute_shader_resource_bindings : 1; @@ -1939,9 +1922,8 @@ struct wined3d_context DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */ DWORD last_was_dual_blend : 1; DWORD padding : 8; - DWORD constant_update_mask; - DWORD numbered_array_mask; + DWORD numbered_array_mask; GLenum tracking_parm; /* Which source is tracking current colour */ GLenum untracked_materials[2]; UINT blit_w, blit_h; @@ -2008,8 +1990,6 @@ struct wined3d_context struct wined3d_fence *buffer_fences[MAX_ATTRIBS]; unsigned int buffer_fence_count; - GLuint blit_vbo; - DWORD tex_unit_map[MAX_COMBINED_SAMPLERS]; DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS]; @@ -2018,9 +1998,6 @@ struct wined3d_context GLfloat fog_coord_value; GLfloat color[4], fogstart, fogend, fogcolor[4]; GLuint dummy_arbfp_prog; - - unsigned int viewport_count; - unsigned int scissor_rect_count; }; struct wined3d_fb_state @@ -2116,6 +2093,8 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_ const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN; +struct wined3d_surface; + enum wined3d_blit_op { WINED3D_BLIT_OP_COLOR_BLIT, @@ -2140,10 +2119,9 @@ struct wined3d_blitter_ops unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil); DWORD (*blitter_blit)(struct wined3d_blitter *blitter, enum wined3d_blit_op op, struct wined3d_context *context, - struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, - const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key, - enum wined3d_texture_filter_type filter); + struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect, + struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter); }; void wined3d_arbfp_blitter_create(struct wined3d_blitter **next, @@ -2153,8 +2131,6 @@ void wined3d_fbo_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; void wined3d_ffp_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; -struct wined3d_blitter *wined3d_glsl_blitter_create(struct wined3d_blitter **next, - const struct wined3d_device *device) DECLSPEC_HIDDEN; void wined3d_raw_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; @@ -2169,10 +2145,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN; void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, - struct wined3d_resource *rt, unsigned int rt_sub_resource_idx, - struct wined3d_resource *ds, unsigned int ds_sub_resource_idx, DWORD location) DECLSPEC_HIDDEN; -void context_apply_ffp_blit_state(struct wined3d_context *context, - const struct wined3d_device *device) DECLSPEC_HIDDEN; + struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN; void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, unsigned int unit) DECLSPEC_HIDDEN; void context_bind_bo(struct wined3d_context *context, GLenum binding, GLuint name) DECLSPEC_HIDDEN; @@ -2187,12 +2160,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, stru const struct wined3d_format *ds_format) DECLSPEC_HIDDEN; HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN; void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; -void context_draw_shaded_quad(struct wined3d_context *context, struct wined3d_texture *texture, - unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect, - enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -void context_draw_textured_quad(struct wined3d_context *context, struct wined3d_texture *texture, - unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect, - enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void context_enable_clip_distances(struct wined3d_context *context, unsigned int mask) DECLSPEC_HIDDEN; void context_end_transform_feedback(struct wined3d_context *context) DECLSPEC_HIDDEN; void context_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN; @@ -2206,16 +2173,14 @@ void context_gl_resource_released(struct wined3d_device *device, GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN; void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN; void context_invalidate_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN; -void context_load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si, - GLuint *current_bo, const struct wined3d_state *state) DECLSPEC_HIDDEN; void *context_map_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data, size_t size, GLenum binding, DWORD flags) DECLSPEC_HIDDEN; struct wined3d_context *context_reacquire(const struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN; -void context_resource_released(const struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -void context_restore(struct wined3d_context *context, struct wined3d_texture *texture, - unsigned int sub_resource_idx) DECLSPEC_HIDDEN; +void context_resource_released(const struct wined3d_device *device, + struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN; +void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) DECLSPEC_HIDDEN; BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN; void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN; void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN; @@ -2223,12 +2188,9 @@ void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; -void context_texture_update(struct wined3d_context *context, const struct wined3d_texture *texture) DECLSPEC_HIDDEN; -void context_unload_tex_coords(const struct wined3d_context *context) DECLSPEC_HIDDEN; +void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) DECLSPEC_HIDDEN; void context_unmap_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data, GLenum binding) DECLSPEC_HIDDEN; -void context_update_stream_sources(struct wined3d_context *context, - const struct wined3d_state *state) DECLSPEC_HIDDEN; /***************************************************************************** * Internal representation of a light @@ -2443,13 +2405,11 @@ enum wined3d_pci_device CARD_NVIDIA_GEFORCE_GTX980 = 0x13c0, CARD_NVIDIA_GEFORCE_GTX980TI = 0x17c8, CARD_NVIDIA_GEFORCE_GTX1050 = 0x1c81, - CARD_NVIDIA_GEFORCE_GTX1050TI = 0x1c82, CARD_NVIDIA_GEFORCE_GTX1060 = 0x1c03, CARD_NVIDIA_GEFORCE_GTX1070 = 0x1b81, CARD_NVIDIA_GEFORCE_GTX1080 = 0x1b80, CARD_NVIDIA_GEFORCE_GTX1080TI = 0x1b06, CARD_NVIDIA_TITANX_PASCAL = 0x1b00, - CARD_NVIDIA_TITANV = 0x1d81, CARD_VMWARE_SVGA3D = 0x0405, @@ -2577,6 +2537,7 @@ struct wined3d_gl_limits UINT texture3d_size; float pointsize_max; float pointsize_min; + UINT blends; UINT anisotropy; float shininess; UINT samples; @@ -2679,11 +2640,17 @@ BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN; -enum wined3d_projection_type +enum projection_types { - WINED3D_PROJECTION_NONE = 0, - WINED3D_PROJECTION_COUNT3 = 1, - WINED3D_PROJECTION_COUNT4 = 2 + proj_none = 0, + proj_count3 = 1, + proj_count4 = 2 +}; + +enum dst_arg +{ + resultreg = 0, + tempreg = 1 }; /***************************************************************************** @@ -2704,7 +2671,7 @@ struct texture_stage_op struct color_fixup_desc color_fixup; unsigned tex_type : 3; - unsigned tmp_dst : 1; + unsigned dst : 1; unsigned projected : 2; unsigned padding : 10; }; @@ -2890,10 +2857,8 @@ struct wined3d_state struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1]; struct wined3d_vec4 clip_planes[MAX_CLIP_DISTANCES]; struct wined3d_material material; - struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS]; - unsigned int viewport_count; - RECT scissor_rects[WINED3D_MAX_VIEWPORTS]; - unsigned int scissor_rect_count; + struct wined3d_viewport viewport; + RECT scissor_rect; /* Light hashmap. Collisions are handled using linked lists. */ #define LIGHTMAP_SIZE 43 @@ -2924,19 +2889,29 @@ static inline BOOL wined3d_dualblend_enabled(const struct wined3d_state *state, struct wined3d_dummy_textures { - GLuint tex_1d; GLuint tex_2d; + GLuint tex_1d; GLuint tex_rect; GLuint tex_3d; GLuint tex_cube; GLuint tex_cube_array; - GLuint tex_1d_array; GLuint tex_2d_array; + GLuint tex_1d_array; GLuint tex_buffer; GLuint tex_2d_ms; GLuint tex_2d_ms_array; }; +#if defined(STAGING_CSMT) +struct wined3d_gl_bo +{ + GLuint name; + GLenum usage; + GLenum type_hint; + UINT size; +}; + +#endif /* STAGING_CSMT */ #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that @@ -2965,12 +2940,13 @@ struct wined3d_device APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1]; struct wined3d_blitter *blitter; + BYTE vertexBlendUsed : 1; /* To avoid needless setting of the blend matrices */ BYTE bCursorVisible : 1; BYTE d3d_initialized : 1; BYTE inScene : 1; /* A flag to check for proper BeginScene / EndScene call pairs */ BYTE softwareVertexProcessing : 1; /* process vertex shaders using software or hardware */ BYTE filter_messages : 1; - BYTE padding : 3; + BYTE padding : 2; unsigned char surface_alignment; /* Line Alignment of surfaces */ @@ -2987,7 +2963,6 @@ struct wined3d_device struct wined3d_rendertarget_view *back_buffer_view; struct wined3d_swapchain **swapchains; UINT swapchain_count; - unsigned int max_frame_latency; struct list resources; /* a linked list to track resources created by the device */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ @@ -3037,6 +3012,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; +#if defined(STAGING_CSMT) +struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage, + GLenum type_hint, struct wined3d_context *context) DECLSPEC_HIDDEN; +void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, + const struct wined3d_context *context) DECLSPEC_HIDDEN; +#endif /* STAGING_CSMT */ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { @@ -3142,16 +3123,16 @@ struct gl_texture GLuint name; }; -struct wined3d_blt_info -{ - GLenum bind_target; - struct wined3d_vec3 texcoords[4]; -}; - struct wined3d_texture_ops { + void (*texture_upload_data)(struct wined3d_texture *texture, unsigned int sub_resource_idx, + const struct wined3d_context *context, const struct wined3d_box *box, + const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch); BOOL (*texture_load_location)(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location); + void (*texture_prepare_texture)(struct wined3d_texture *texture, + struct wined3d_context *context, BOOL srgb); + void (*texture_cleanup_sub_resources)(struct wined3d_texture *texture); }; #define WINED3D_TEXTURE_COND_NP2 0x00000001 @@ -3217,32 +3198,30 @@ struct wined3d_texture { struct list entry; struct list overlays; - struct wined3d_texture *dst_texture; - unsigned int dst_sub_resource_idx; + struct wined3d_surface *dst; RECT src_rect; RECT dst_rect; } *overlay_info; - struct wined3d_dc_info - { - HBITMAP bitmap; - HDC dc; - } *dc_info; - - struct list renderbuffers; - const struct wined3d_renderbuffer_entry *current_renderbuffer; - struct wined3d_texture_sub_resource { void *parent; const struct wined3d_parent_ops *parent_ops; + union + { + struct wined3d_surface *surface; + } u; unsigned int offset; unsigned int size; unsigned int map_count; DWORD locations; +#if !defined(STAGING_CSMT) GLuint buffer_object; +#else /* STAGING_CSMT */ + struct wined3d_gl_bo *buffer; +#endif /* STAGING_CSMT */ } sub_resources[1]; }; @@ -3304,32 +3283,6 @@ static inline unsigned int wined3d_texture_get_level_pow2_height(const struct wi return max(1, texture->pow2_height >> level); } -static inline void wined3d_texture_get_level_box(const struct wined3d_texture *texture, - unsigned int level, struct wined3d_box *box) -{ - wined3d_box_set(box, 0, 0, - wined3d_texture_get_level_width(texture, level), - wined3d_texture_get_level_height(texture, level), - 0, wined3d_texture_get_level_depth(texture, level)); -} - -HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - const struct wined3d_box *dst_box, struct wined3d_texture *src_texture, - unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, - const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -void texture2d_get_blt_info(const struct wined3d_texture *texture, unsigned int sub_resource_idx, - const RECT *rect, struct wined3d_blt_info *info) DECLSPEC_HIDDEN; -BOOL texture2d_load_drawable(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context) DECLSPEC_HIDDEN; -void texture2d_load_fb_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx, - BOOL srgb, struct wined3d_context *context) DECLSPEC_HIDDEN; -BOOL texture2d_load_renderbuffer(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, DWORD dst_location) DECLSPEC_HIDDEN; -BOOL texture2d_load_sysmem(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, DWORD dst_location) DECLSPEC_HIDDEN; -BOOL texture2d_load_texture(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; - void wined3d_texture_apply_sampler_desc(struct wined3d_texture *texture, const struct wined3d_sampler_desc *sampler_desc, const struct wined3d_context *context) DECLSPEC_HIDDEN; void wined3d_texture_bind(struct wined3d_texture *texture, @@ -3351,20 +3304,12 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; -void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture, - unsigned int level, const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN; void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN; void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, - HWND window, RECT *rect) DECLSPEC_HIDDEN; void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box, - const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch, - unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) DECLSPEC_HIDDEN; -void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, - unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture, - unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN; + const struct wined3d_context *context, const struct wined3d_box *box, + const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) DECLSPEC_HIDDEN; void wined3d_texture_validate_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN; @@ -3412,6 +3357,49 @@ struct fbo_entry } key; }; +struct wined3d_surface +{ + struct wined3d_texture *container; + + unsigned int texture_level; + unsigned int texture_layer; + + /* For GetDC */ + HBITMAP bitmap; + HDC dc; + + struct list renderbuffers; + const struct wined3d_renderbuffer_entry *current_renderbuffer; +}; + +static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface) +{ + return surface->texture_layer * surface->container->level_count + surface->texture_level; +} + +static inline struct wined3d_texture_sub_resource *surface_get_sub_resource(struct wined3d_surface *surface) +{ + return &surface->container->sub_resources[surface_get_sub_resource_idx(surface)]; +} + +HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; +void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, + struct wined3d_context *context) DECLSPEC_HIDDEN; +BOOL surface_load_location(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; +void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, + const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN; +void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN; +void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, + const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, + BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; + +void draw_textured_quad(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect, + enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + struct wined3d_sampler { struct wine_rb_entry entry; @@ -3562,7 +3550,9 @@ struct wined3d_cs_queue struct wined3d_cs_ops { +#if defined(STAGING_CSMT) BOOL (*check_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id); +#endif /* STAGING_CSMT */ void *(*require_space)(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id); void (*submit)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id); void (*finish)(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id); @@ -3622,7 +3612,7 @@ void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, - const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, DWORD flags) DECLSPEC_HIDDEN; + const RECT *dst_rect, HWND dst_window_override, DWORD swap_interval, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) DECLSPEC_HIDDEN; @@ -3653,7 +3643,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type UINT sampler_idx, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, enum wined3d_sampler_state state, DWORD value) DECLSPEC_HIDDEN; -void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects) DECLSPEC_HIDDEN; +void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, @@ -3672,7 +3662,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined unsigned int initial_count) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; -void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, const struct wined3d_viewport *viewports) DECLSPEC_HIDDEN; +void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, @@ -3780,6 +3770,19 @@ struct wined3d_rendertarget_view struct wined3d_view_desc desc; }; +static inline struct wined3d_surface *wined3d_rendertarget_view_get_surface( + const struct wined3d_rendertarget_view *view) +{ + struct wined3d_texture *texture; + + if (!view || view->resource->type != WINED3D_RTYPE_TEXTURE_2D) + return NULL; + + texture = texture_from_resource(view->resource); + + return texture->sub_resources[view->sub_resource_idx].u.surface; +} + void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view, const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, @@ -3858,8 +3861,6 @@ struct wined3d_swapchain const struct wined3d_format *ds_format; struct wined3d_palette *palette; RECT front_buffer_update; - unsigned int swap_interval; - unsigned int max_frame_latency; LONG prev_time, frames; /* Performance tracking */ @@ -3874,14 +3875,11 @@ struct wined3d_swapchain }; void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate) DECLSPEC_HIDDEN; -void wined3d_swapchain_set_swap_interval(struct wined3d_swapchain *swapchain, - unsigned int swap_interval) DECLSPEC_HIDDEN; struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, - const struct wined3d_device *device) DECLSPEC_HIDDEN; +void swapchain_update_swap_interval(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; /***************************************************************************** * Utility function prototypes @@ -3956,7 +3954,6 @@ void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN; -enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) DECLSPEC_HIDDEN; /* Math utils */ void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1, @@ -4153,14 +4150,13 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) /* oPos */ return FALSE; - case WINED3DSPR_CONSTBOOL: /* b# */ case WINED3DSPR_DEPTHOUT: /* oDepth */ case WINED3DSPR_DEPTHOUTGE: case WINED3DSPR_DEPTHOUTLE: + case WINED3DSPR_CONSTBOOL: /* b# */ case WINED3DSPR_LOOP: /* aL */ case WINED3DSPR_PREDICATE: /* p0 */ case WINED3DSPR_PRIMID: /* primID */ - case WINED3DSPR_SAMPLEMASK: /* oMask */ return TRUE; case WINED3DSPR_MISCTYPE: @@ -4183,28 +4179,24 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) } static inline void shader_get_position_fixup(const struct wined3d_context *context, - const struct wined3d_state *state, unsigned int fixup_count, float *position_fixup) + const struct wined3d_state *state, float *position_fixup) { float center_offset; - unsigned int i; if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER) center_offset = 63.0f / 64.0f; else center_offset = -1.0f / 64.0f; - for (i = 0; i < fixup_count; ++i) - { - position_fixup[4 * i ] = 1.0f; - position_fixup[4 * i + 1] = 1.0f; - position_fixup[4 * i + 2] = center_offset / state->viewports[i].width; - position_fixup[4 * i + 3] = -center_offset / state->viewports[i].height; + position_fixup[0] = 1.0f; + position_fixup[1] = 1.0f; + position_fixup[2] = center_offset / state->viewport.width; + position_fixup[3] = -center_offset / state->viewport.height; - if (context->render_offscreen) - { - position_fixup[4 * i + 1] *= -1.0f; - position_fixup[4 * i + 3] *= -1.0f; - } + if (context->render_offscreen) + { + position_fixup[1] *= -1.0f; + position_fixup[3] *= -1.0f; } } @@ -4308,8 +4300,8 @@ struct wined3d_rational struct wined3d_color_key_conversion { enum wined3d_format_id dst_format; - void (*convert)(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, - unsigned int width, unsigned int height, const struct wined3d_color_key *colour_key); + void (*convert)(const BYTE *src, unsigned int src_pitch, BYTE *dst, unsigned int dst_pitch, unsigned int width, + unsigned int height, const struct wined3d_palette *palette, const struct wined3d_color_key *color_key); }; struct wined3d_format @@ -4527,6 +4519,15 @@ static inline void wined3d_insert_bits(DWORD *bitstream, } } +static inline struct wined3d_surface *context_get_rt_surface(const struct wined3d_context *context) +{ + struct wined3d_texture *texture = context->current_rt.texture; + + if (!texture) + return NULL; + return texture->sub_resources[context->current_rt.sub_resource_idx].u.surface; +} + static inline void wined3d_from_cs(const struct wined3d_cs *cs) { if (cs->thread) diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 74f5027954f..c6f0d42d836 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -22,13 +22,13 @@ sdk/tools/wpp # Synced to WineStaging-2.9 The following libraries are shared with Wine. dll/directx/wine/amstream # Synced to WineStaging-3.9 -dll/directx/wine/d3d8 # Synced to WineStaging-3.9 -dll/directx/wine/d3d9 # Synced to WineStaging-3.9 -dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-4.0 +dll/directx/wine/d3d8 # Synced to WineStaging-3.3 +dll/directx/wine/d3d9 # Synced to WineStaging-3.3 +dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3 dll/directx/wine/d3drm # Synced to WineStaging-4.0 dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-4.0 dll/directx/wine/d3dxof # Synced to WineStaging-3.17 -dll/directx/wine/ddraw # Synced to WineStaging-3.9 +dll/directx/wine/ddraw # Synced to WineStaging-3.3 dll/directx/wine/devenum # Synced to WineStaging-3.9 dll/directx/wine/dinput # Synced to WineStaging-4.0 dll/directx/wine/dinput8 # Synced to WineStaging-3.3 @@ -41,7 +41,7 @@ dll/directx/wine/dxdiagn # Synced to WineStaging-3.3 dll/directx/wine/msdmo # Synced to WineStaging-3.17 dll/directx/wine/qedit # Synced to WineStaging-3.17 dll/directx/wine/quartz # Synced to WineStaging-3.9 -dll/directx/wine/wined3d # Synced to WineStaging-3.9 +dll/directx/wine/wined3d # Synced to WineStaging-3.3 dll/win32/activeds # Synced to WineStaging-3.3 dll/win32/actxprxy # Synced to WineStaging-3.3 diff --git a/sdk/include/reactos/wine/wined3d.h b/sdk/include/reactos/wine/wined3d.h index dab9371330d..1f8171d9c6b 100644 --- a/sdk/include/reactos/wine/wined3d.h +++ b/sdk/include/reactos/wine/wined3d.h @@ -388,11 +388,12 @@ enum wined3d_render_state WINED3D_RS_SRCBLENDALPHA = 207, WINED3D_RS_DESTBLENDALPHA = 208, WINED3D_RS_BLENDOPALPHA = 209, - WINED3D_RS_DEPTHBIASCLAMP = 210, - WINED3D_RS_COLORWRITEENABLE4 = 211, - WINED3D_RS_COLORWRITEENABLE5 = 212, - WINED3D_RS_COLORWRITEENABLE6 = 213, - WINED3D_RS_COLORWRITEENABLE7 = 214, + WINED3D_RS_DEPTHCLIP = 210, + WINED3D_RS_DEPTHBIASCLAMP = 211, + WINED3D_RS_COLORWRITEENABLE4 = 212, + WINED3D_RS_COLORWRITEENABLE5 = 213, + WINED3D_RS_COLORWRITEENABLE6 = 214, + WINED3D_RS_COLORWRITEENABLE7 = 215, }; #define WINEHIGHEST_RENDER_STATE WINED3D_RS_COLORWRITEENABLE7 @@ -530,16 +531,6 @@ enum wined3d_swap_effect WINED3D_SWAP_EFFECT_OVERLAY, }; -enum wined3d_swap_interval -{ - WINED3D_SWAP_INTERVAL_IMMEDIATE = 0, - WINED3D_SWAP_INTERVAL_ONE = 1, - WINED3D_SWAP_INTERVAL_TWO = 2, - WINED3D_SWAP_INTERVAL_THREE = 3, - WINED3D_SWAP_INTERVAL_FOUR = 4, - WINED3D_SWAP_INTERVAL_DEFAULT = ~0u, -}; - enum wined3d_sampler_state { WINED3D_SAMP_ADDRESS_U = 1, @@ -599,7 +590,7 @@ enum wined3d_texture_stage_state WINED3D_TSS_ALPHA_ARG0 = 15, WINED3D_TSS_RESULT_ARG = 16, WINED3D_TSS_CONSTANT = 17, - WINED3D_TSS_INVALID = ~0u, + WINED3D_TSS_INVALID = ~0U, }; #define WINED3D_HIGHEST_TEXTURE_STATE WINED3D_TSS_CONSTANT @@ -949,6 +940,13 @@ enum wined3d_shader_byte_code_format #define WINED3DPRESENT_RATE_DEFAULT 0x00000000 +#define WINED3DPRESENT_INTERVAL_DEFAULT 0x00000000 +#define WINED3DPRESENT_INTERVAL_ONE 0x00000001 +#define WINED3DPRESENT_INTERVAL_TWO 0x00000002 +#define WINED3DPRESENT_INTERVAL_THREE 0x00000004 +#define WINED3DPRESENT_INTERVAL_FOUR 0x00000008 +#define WINED3DPRESENT_INTERVAL_IMMEDIATE 0x80000000 + #define WINED3DCLIPPLANE0 (1u << 0) #define WINED3DCLIPPLANE1 (1u << 1) #define WINED3DCLIPPLANE2 (1u << 2) @@ -1328,6 +1326,8 @@ enum wined3d_shader_byte_code_format #define WINED3D_NO_PRIMITIVE_RESTART 0x00000800 #define WINED3D_LEGACY_CUBEMAP_FILTERING 0x00001000 #define WINED3D_NORMALIZED_DEPTH_BIAS 0x00002000 +#define WINED3D_REQUEST_D3D10 0x00004000 +#define WINED3D_LIMIT_VIEWPORT 0x00008000 #define WINED3D_RESZ_CODE 0x7fa05000 @@ -1576,8 +1576,6 @@ enum wined3d_shader_byte_code_format #define WINED3D_VIEW_TEXTURE_CUBE 0x00000008 #define WINED3D_VIEW_TEXTURE_ARRAY 0x00000010 -#define WINED3D_MAX_VIEWPORTS 16 - struct wined3d_display_mode { UINT width; @@ -1731,10 +1729,10 @@ struct wined3d_adapter_identifier struct wined3d_swapchain_desc { - unsigned int backbuffer_width; - unsigned int backbuffer_height; + UINT backbuffer_width; + UINT backbuffer_height; enum wined3d_format_id backbuffer_format; - unsigned int backbuffer_count; + UINT backbuffer_count; DWORD backbuffer_usage; enum wined3d_multisample_type multisample_type; DWORD multisample_quality; @@ -1744,7 +1742,8 @@ struct wined3d_swapchain_desc BOOL enable_auto_depth_stencil; enum wined3d_format_id auto_depth_stencil_format; DWORD flags; - unsigned int refresh_rate; + UINT refresh_rate; + UINT swap_interval; BOOL auto_restore_display_mode; }; @@ -1890,6 +1889,7 @@ typedef struct _WINED3DCAPS DWORD Caps; DWORD Caps2; DWORD Caps3; + DWORD PresentationIntervals; DWORD CursorCaps; DWORD DevCaps; @@ -2008,7 +2008,6 @@ struct wined3d_blend_state_desc struct wined3d_rasterizer_state_desc { BOOL front_ccw; - BOOL depth_clip; }; struct wined3d_sampler_desc @@ -2139,8 +2138,11 @@ struct wined3d_device_parent_ops void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device); void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent); void (__cdecl *activate)(struct wined3d_device_parent *device_parent, BOOL activate); - HRESULT (__cdecl *texture_sub_resource_created)(struct wined3d_device_parent *device_parent, - enum wined3d_resource_type type, struct wined3d_texture *texture, unsigned int sub_resource_idx, + HRESULT (__cdecl *surface_created)(struct wined3d_device_parent *device_parent, + struct wined3d_texture *texture, unsigned int sub_resource_idx, + void **parent, const struct wined3d_parent_ops **parent_ops); + HRESULT (__cdecl *volume_created)(struct wined3d_device_parent *device_parent, + struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, void **parent, const struct wined3d_parent_ops **parent_ops); HRESULT (__cdecl *create_swapchain_texture)(struct wined3d_device_parent *device_parent, void *parent, const struct wined3d_resource_desc *desc, DWORD texture_flags, struct wined3d_texture **texture); @@ -2237,7 +2239,7 @@ void __cdecl wined3d_device_copy_resource(struct wined3d_device *device, HRESULT __cdecl wined3d_device_copy_sub_resource_region(struct wined3d_device *device, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource, - unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags); + unsigned int src_sub_resource_idx, const struct wined3d_box *src_box); void __cdecl wined3d_device_copy_uav_counter(struct wined3d_device *device, struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav); HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, @@ -2304,7 +2306,6 @@ HRESULT __cdecl wined3d_device_get_light(const struct wined3d_device *device, UINT light_idx, struct wined3d_light *light); HRESULT __cdecl wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable); void __cdecl wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material); -unsigned int __cdecl wined3d_device_get_max_frame_latency(const struct wined3d_device *device); float __cdecl wined3d_device_get_npatch_mode(const struct wined3d_device *device); struct wined3d_shader * __cdecl wined3d_device_get_pixel_shader(const struct wined3d_device *device); struct wined3d_query * __cdecl wined3d_device_get_predication(struct wined3d_device *device, BOOL *value); @@ -2328,8 +2329,7 @@ struct wined3d_rendertarget_view * __cdecl wined3d_device_get_rendertarget_view( unsigned int view_idx); DWORD __cdecl wined3d_device_get_sampler_state(const struct wined3d_device *device, UINT sampler_idx, enum wined3d_sampler_state state); -void __cdecl wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count, - RECT *rect); +void __cdecl wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect); BOOL __cdecl wined3d_device_get_software_vertex_processing(const struct wined3d_device *device); struct wined3d_buffer * __cdecl wined3d_device_get_stream_output(struct wined3d_device *device, UINT idx, UINT *offset); @@ -2349,8 +2349,7 @@ struct wined3d_unordered_access_view * __cdecl wined3d_device_get_unordered_acce const struct wined3d_device *device, unsigned int idx); struct wined3d_vertex_declaration * __cdecl wined3d_device_get_vertex_declaration(const struct wined3d_device *device); struct wined3d_shader * __cdecl wined3d_device_get_vertex_shader(const struct wined3d_device *device); -void __cdecl wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count, - struct wined3d_viewport *viewports); +void __cdecl wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport); struct wined3d_buffer * __cdecl wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx); HRESULT __cdecl wined3d_device_get_vs_consts_b(const struct wined3d_device *device, unsigned int start_idx, unsigned int count, BOOL *constants); @@ -2426,7 +2425,6 @@ HRESULT __cdecl wined3d_device_set_light(struct wined3d_device *device, UINT light_idx, const struct wined3d_light *light); HRESULT __cdecl wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable); void __cdecl wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material); -void __cdecl wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int max_frame_latency); void __cdecl wined3d_device_set_multithreaded(struct wined3d_device *device); HRESULT __cdecl wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments); void __cdecl wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader); @@ -2452,8 +2450,7 @@ HRESULT __cdecl wined3d_device_set_rendertarget_view(struct wined3d_device *devi unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport); void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device, UINT sampler_idx, enum wined3d_sampler_state state, DWORD value); -void __cdecl wined3d_device_set_scissor_rects(struct wined3d_device *device, - unsigned int rect_count, const RECT *rect); +void __cdecl wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect); void __cdecl wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software); void __cdecl wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer, UINT offset); @@ -2470,8 +2467,7 @@ void __cdecl wined3d_device_set_unordered_access_view(struct wined3d_device *dev void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device, struct wined3d_vertex_declaration *declaration); void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader); -void __cdecl wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count, - const struct wined3d_viewport *viewports); +void __cdecl wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport); void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer); HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device, unsigned int start_idx, unsigned int count, const BOOL *constants); @@ -2488,7 +2484,7 @@ HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device); HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device); void __cdecl wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, - unsigned int depth_pitch, unsigned int flags); + unsigned int depth_pitch); HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device, struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture); HRESULT __cdecl wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes); @@ -2689,8 +2685,8 @@ void __cdecl wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchai HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain, struct wined3d_raster_status *raster_status); ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain); -HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, - const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, DWORD flags); +HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, + const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD swap_interval, DWORD flags); HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count, unsigned int width, unsigned int height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, unsigned int multisample_quality); -- 2.17.1