From 5989fa66ddfa15accc2e6712665734df9592f648 Mon Sep 17 00:00:00 2001 From: Kamil Hornicek Date: Thu, 27 May 2010 10:25:14 +0000 Subject: [PATCH] - Sync wined3d, ddraw, d3d8, d3d9 with Wine svn path=/trunk/; revision=47371 --- reactos/dll/directx/wine/d3d8/device.c | 36 +- reactos/dll/directx/wine/d3d9/device.c | 30 + reactos/dll/directx/wine/ddraw/ddraw.c | 35 +- reactos/dll/directx/wine/ddraw/ddraw_thunks.c | 3 + reactos/dll/directx/wine/ddraw/device.c | 120 +- reactos/dll/directx/wine/ddraw/direct3d.c | 1 + .../dll/directx/wine/ddraw/executebuffer.c | 4 +- reactos/dll/directx/wine/ddraw/main.c | 2 +- reactos/dll/directx/wine/ddraw/material.c | 1 - reactos/dll/directx/wine/ddraw/utils.c | 6 +- .../directx/wine/wined3d/arb_program_shader.c | 791 +++-- .../wine/wined3d/ati_fragment_shader.c | 219 +- .../dll/directx/wine/wined3d/basetexture.c | 95 +- reactos/dll/directx/wine/wined3d/buffer.c | 366 ++- reactos/dll/directx/wine/wined3d/context.c | 1330 ++++---- .../dll/directx/wine/wined3d/cubetexture.c | 258 +- reactos/dll/directx/wine/wined3d/device.c | 1652 +++++----- reactos/dll/directx/wine/wined3d/directx.c | 1134 +++---- reactos/dll/directx/wine/wined3d/drawprim.c | 133 +- .../dll/directx/wine/wined3d/glsl_shader.c | 441 ++- .../wine/wined3d/nvidia_texture_shader.c | 192 +- reactos/dll/directx/wine/wined3d/palette.c | 35 +- reactos/dll/directx/wine/wined3d/query.c | 122 +- reactos/dll/directx/wine/wined3d/resource.c | 10 +- reactos/dll/directx/wine/wined3d/shader.c | 15 +- reactos/dll/directx/wine/wined3d/state.c | 759 +++-- reactos/dll/directx/wine/wined3d/stateblock.c | 71 +- reactos/dll/directx/wine/wined3d/surface.c | 2858 ++++++++--------- .../dll/directx/wine/wined3d/surface_base.c | 288 +- .../dll/directx/wine/wined3d/surface_gdi.c | 18 +- reactos/dll/directx/wine/wined3d/swapchain.c | 268 +- .../dll/directx/wine/wined3d/swapchain_base.c | 26 +- .../dll/directx/wine/wined3d/swapchain_gdi.c | 30 +- reactos/dll/directx/wine/wined3d/texture.c | 202 +- reactos/dll/directx/wine/wined3d/utils.c | 1100 ++++--- reactos/dll/directx/wine/wined3d/view.c | 12 +- reactos/dll/directx/wine/wined3d/volume.c | 11 +- .../dll/directx/wine/wined3d/volumetexture.c | 157 +- reactos/dll/directx/wine/wined3d/wined3d_gl.h | 60 +- .../dll/directx/wine/wined3d/wined3d_main.c | 54 +- .../directx/wine/wined3d/wined3d_private.h | 334 +- reactos/include/reactos/wine/wined3d.idl | 51 +- 42 files changed, 7269 insertions(+), 6061 deletions(-) diff --git a/reactos/dll/directx/wine/d3d8/device.c b/reactos/dll/directx/wine/d3d8/device.c index 11697b2ff26..12ed0fbfd38 100644 --- a/reactos/dll/directx/wine/d3d8/device.c +++ b/reactos/dll/directx/wine/d3d8/device.c @@ -171,18 +171,19 @@ static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enu if (t->free_entries) { + DWORD index = t->free_entries - t->entries; /* Use a free handle */ entry = t->free_entries; if (entry->type != D3D8_HANDLE_FREE) { - ERR("Handle %u(%p) is in the free list, but has type %#x.\n", (entry - t->entries), entry, entry->type); + ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type); return D3D8_INVALID_HANDLE; } t->free_entries = entry->object; entry->object = object; entry->type = type; - return entry - t->entries; + return index; } if (!(t->entry_count < t->table_size)) @@ -324,6 +325,7 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) { HeapFree(GetProcessHeap(), 0, This->decls); IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroySwapChain); + IWineD3DDevice_ReleaseFocusWindow(This->WineD3DDevice); IWineD3DDevice_Release(This->WineD3DDevice); HeapFree(GetProcessHeap(), 0, This->handle_table.entries); HeapFree(GetProcessHeap(), 0, This); @@ -2762,6 +2764,19 @@ static const IWineD3DDeviceParentVtbl d3d8_wined3d_device_parent_vtbl = device_parent_CreateSwapChain, }; +static void setup_fpu(void) +{ + WORD cw; + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xf3f) | 0x3f; + __asm__ volatile ("fldcw %0" : : "m" (cw)); +#else + FIXME("FPU setup not implemented for this platform.\n"); +#endif +} + HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) { @@ -2780,6 +2795,8 @@ HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapte } device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE; + if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); + wined3d_mutex_lock(); hr = IWineD3D_CreateDevice(wined3d, adapter, device_type, focus_window, flags, (IUnknown *)device, (IWineD3DDeviceParent *)&device->device_parent_vtbl, &device->WineD3DDevice); @@ -2791,6 +2808,19 @@ HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapte return hr; } + if (!parameters->Windowed) + { + if (!focus_window) focus_window = parameters->hDeviceWindow; + if (FAILED(hr = IWineD3DDevice_AcquireFocusWindow(device->WineD3DDevice, focus_window))) + { + ERR("Failed to acquire focus window, hr %#x.\n", hr); + IWineD3DDevice_Release(device->WineD3DDevice); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + return hr; + } + } + if (flags & D3DCREATE_MULTITHREADED) IWineD3DDevice_SetMultithreaded(device->WineD3DDevice); wined3d_parameters.BackBufferWidth = parameters->BackBufferWidth; @@ -2813,6 +2843,7 @@ HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapte if (FAILED(hr)) { WARN("Failed to initialize 3D, hr %#x.\n", hr); + IWineD3DDevice_ReleaseFocusWindow(device->WineD3DDevice); IWineD3DDevice_Release(device->WineD3DDevice); wined3d_mutex_unlock(); HeapFree(GetProcessHeap(), 0, device->handle_table.entries); @@ -2855,6 +2886,7 @@ HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapte err: wined3d_mutex_lock(); IWineD3DDevice_Uninit3D(device->WineD3DDevice, D3D8CB_DestroySwapChain); + IWineD3DDevice_ReleaseFocusWindow(device->WineD3DDevice); IWineD3DDevice_Release(device->WineD3DDevice); wined3d_mutex_unlock(); HeapFree(GetProcessHeap(), 0, device->handle_table.entries); diff --git a/reactos/dll/directx/wine/d3d9/device.c b/reactos/dll/directx/wine/d3d9/device.c index 79a9ba01834..b9f539e0b28 100644 --- a/reactos/dll/directx/wine/d3d9/device.c +++ b/reactos/dll/directx/wine/d3d9/device.c @@ -271,6 +271,7 @@ static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(LPDIRECT3DDEV HeapFree(GetProcessHeap(), 0, This->convertedDecls); IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroySwapChain); + IWineD3DDevice_ReleaseFocusWindow(This->WineD3DDevice); IWineD3DDevice_Release(This->WineD3DDevice); wined3d_mutex_unlock(); @@ -2821,6 +2822,19 @@ static const IWineD3DDeviceParentVtbl d3d9_wined3d_device_parent_vtbl = device_parent_CreateSwapChain, }; +static void setup_fpu(void) +{ + WORD cw; + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xf3f) | 0x3f; + __asm__ volatile ("fldcw %0" : : "m" (cw)); +#else + FIXME("FPU setup not implemented for this platform.\n"); +#endif +} + HRESULT device_init(IDirect3DDevice9Impl *device, IWineD3D *wined3d, UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) { @@ -2832,6 +2846,8 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IWineD3D *wined3d, UINT adapte device->device_parent_vtbl = &d3d9_wined3d_device_parent_vtbl; device->ref = 1; + if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); + wined3d_mutex_lock(); hr = IWineD3D_CreateDevice(wined3d, adapter, device_type, focus_window, flags, (IUnknown *)device, (IWineD3DDeviceParent *)&device->device_parent_vtbl, &device->WineD3DDevice); @@ -2842,6 +2858,18 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IWineD3D *wined3d, UINT adapte return hr; } + if (!parameters->Windowed) + { + if (!focus_window) focus_window = parameters->hDeviceWindow; + if (FAILED(hr = IWineD3DDevice_AcquireFocusWindow(device->WineD3DDevice, focus_window))) + { + ERR("Failed to acquire focus window, hr %#x.\n", hr); + IWineD3DDevice_Release(device->WineD3DDevice); + wined3d_mutex_unlock(); + return hr; + } + } + if (flags & D3DCREATE_ADAPTERGROUP_DEVICE) { WINED3DCAPS caps; @@ -2885,6 +2913,7 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IWineD3D *wined3d, UINT adapte if (FAILED(hr)) { WARN("Failed to initialize 3D, hr %#x.\n", hr); + IWineD3DDevice_ReleaseFocusWindow(device->WineD3DDevice); HeapFree(GetProcessHeap(), 0, wined3d_parameters); IWineD3DDevice_Release(device->WineD3DDevice); wined3d_mutex_unlock(); @@ -2921,6 +2950,7 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IWineD3D *wined3d, UINT adapte ERR("Failed to allocate FVF vertex declaration map memory.\n"); wined3d_mutex_lock(); IWineD3DDevice_Uninit3D(device->WineD3DDevice, D3D9CB_DestroySwapChain); + IWineD3DDevice_ReleaseFocusWindow(device->WineD3DDevice); IWineD3DDevice_Release(device->WineD3DDevice); wined3d_mutex_unlock(); return E_OUTOFMEMORY; diff --git a/reactos/dll/directx/wine/ddraw/ddraw.c b/reactos/dll/directx/wine/ddraw/ddraw.c index 122c31b8cb8..a7522f91789 100644 --- a/reactos/dll/directx/wine/ddraw/ddraw.c +++ b/reactos/dll/directx/wine/ddraw/ddraw.c @@ -264,8 +264,8 @@ IDirectDrawImpl_AddRef(IDirectDraw7 *iface) void IDirectDrawImpl_Destroy(IDirectDrawImpl *This) { - /* Clear the cooplevel to restore window and display mode */ IDirectDraw7_SetCooperativeLevel((IDirectDraw7 *)This, NULL, DDSCL_NORMAL); + IDirectDraw7_RestoreDisplayMode((IDirectDraw7 *)This); /* Destroy the device window if we created one */ if(This->devicewindow != 0) @@ -441,12 +441,11 @@ IDirectDrawImpl_SetCooperativeLevel(IDirectDraw7 *iface, /* Switching from fullscreen? */ if(This->cooperative_level & DDSCL_FULLSCREEN) { - /* Restore the display mode */ - IDirectDraw7_RestoreDisplayMode(iface); - This->cooperative_level &= ~DDSCL_FULLSCREEN; This->cooperative_level &= ~DDSCL_EXCLUSIVE; This->cooperative_level &= ~DDSCL_ALLOWMODEX; + + IWineD3DDevice_ReleaseFocusWindow(This->wineD3DDevice); } /* Don't override focus windows or private device windows */ @@ -483,6 +482,13 @@ IDirectDrawImpl_SetCooperativeLevel(IDirectDraw7 *iface, !(This->devicewindow) && (hwnd != window) ) { + HRESULT hr = IWineD3DDevice_AcquireFocusWindow(This->wineD3DDevice, hwnd); + if (FAILED(hr)) + { + ERR("Failed to acquire focus window, hr %#x.\n", hr); + LeaveCriticalSection(&ddraw_cs); + return hr; + } This->dest_window = hwnd; } } @@ -1514,11 +1520,24 @@ IDirectDrawImpl_GetSurfaceFromDC(IDirectDraw7 *iface, IDirectDrawSurface7 **Surface) { IDirectDrawImpl *This = (IDirectDrawImpl *)iface; - FIXME("(%p)->(%p,%p): Stub!\n", This, hdc, Surface); + IWineD3DSurface *wined3d_surface; + HRESULT hr; + + TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface); - /* Implementation idea if needed: Loop through all surfaces and compare - * their hdc with hdc. Implement it in WineD3D! */ - return DDERR_NOTFOUND; + if (!Surface) return E_INVALIDARG; + + hr = IWineD3DDevice_GetSurfaceFromDC(This->wineD3DDevice, hdc, &wined3d_surface); + if (FAILED(hr)) + { + TRACE("No surface found for dc %p.\n", hdc); + *Surface = NULL; + return DDERR_NOTFOUND; + } + + IWineD3DSurface_GetParent(wined3d_surface, (IUnknown **)Surface); + TRACE("Returning surface %p.\n", Surface); + return DD_OK; } /***************************************************************************** diff --git a/reactos/dll/directx/wine/ddraw/ddraw_thunks.c b/reactos/dll/directx/wine/ddraw/ddraw_thunks.c index dc71bf55a9c..9d606245272 100644 --- a/reactos/dll/directx/wine/ddraw/ddraw_thunks.c +++ b/reactos/dll/directx/wine/ddraw/ddraw_thunks.c @@ -290,6 +290,7 @@ IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc, set_surf_version(impl, 1); IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw1(This)); impl->ifaceToRelease = NULL; + return hr; } @@ -309,11 +310,13 @@ IDirectDraw2Impl_CreateSurface(LPDIRECTDRAW2 This, LPDDSURFACEDESC pSDesc, *ppSurface = NULL; return hr; } + impl = (IDirectDrawSurfaceImpl *)pSurface7; *ppSurface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl; set_surf_version(impl, 2); IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw2(This)); impl->ifaceToRelease = NULL; + return hr; } diff --git a/reactos/dll/directx/wine/ddraw/device.c b/reactos/dll/directx/wine/ddraw/device.c index 13ecfa133ac..9a4e5c73204 100644 --- a/reactos/dll/directx/wine/ddraw/device.c +++ b/reactos/dll/directx/wine/ddraw/device.c @@ -2409,22 +2409,60 @@ IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface, case D3DRENDERSTATE_TEXTUREMIN: { WINED3DTEXTUREFILTERTYPE tex_min; + WINED3DTEXTUREFILTERTYPE tex_mip; hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, - 0, WINED3DSAMP_MINFILTER, - &tex_min); + 0, WINED3DSAMP_MINFILTER, &tex_min); + if (FAILED(hr)) + { + LeaveCriticalSection(&ddraw_cs); + return hr; + } + hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, + 0, WINED3DSAMP_MIPFILTER, &tex_mip); switch (tex_min) { case WINED3DTEXF_POINT: - *Value = D3DFILTER_NEAREST; + switch (tex_mip) + { + case WINED3DTEXF_NONE: + *Value = D3DFILTER_NEAREST; + break; + case WINED3DTEXF_POINT: + *Value = D3DFILTER_MIPNEAREST; + break; + case WINED3DTEXF_LINEAR: + *Value = D3DFILTER_LINEARMIPNEAREST; + break; + default: + ERR("Unhandled mip filter %#x.\n", tex_mip); + *Value = D3DFILTER_NEAREST; + break; + } break; case WINED3DTEXF_LINEAR: - *Value = D3DFILTER_LINEAR; + switch (tex_mip) + { + case WINED3DTEXF_NONE: + *Value = D3DFILTER_LINEAR; + break; + case WINED3DTEXF_POINT: + *Value = D3DFILTER_MIPLINEAR; + break; + case WINED3DTEXF_LINEAR: + *Value = D3DFILTER_LINEARMIPLINEAR; + break; + default: + ERR("Unhandled mip filter %#x.\n", tex_mip); + *Value = D3DFILTER_LINEAR; + break; + } break; default: - ERR("Unhandled texture mag %d !\n",tex_min); - *Value = 0; + ERR("Unhandled texture min filter %#x.\n",tex_min); + *Value = D3DFILTER_NEAREST; + break; } break; } @@ -2441,8 +2479,20 @@ IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface, Value); break; + case D3DRENDERSTATE_BORDERCOLOR: + FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n"); + hr = E_NOTIMPL; + break; + default: - /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */ + if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00 + && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31) + { + FIXME("Unhandled stipple pattern render state (%#x).\n", + RenderStateType); + hr = E_NOTIMPL; + break; + } hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice, RenderStateType, Value); @@ -2640,22 +2690,39 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, /* Some render states need special care */ switch(RenderStateType) { + /* + * The ddraw texture filter mapping works like this: + * D3DFILTER_NEAREST Point min/mag, no mip + * D3DFILTER_MIPNEAREST Point min/mag, point mip + * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip + * + * D3DFILTER_LINEAR Linear min/mag, no mip + * D3DFILTER_MIPLINEAR Linear min/mag, point mip + * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip + * + * This is the opposite of the GL naming convention, + * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR. + */ case D3DRENDERSTATE_TEXTUREMAG: { - WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_POINT; + WINED3DTEXTUREFILTERTYPE tex_mag; - switch ((D3DTEXTUREFILTER) Value) + switch (Value) { case D3DFILTER_NEAREST: + case D3DFILTER_MIPNEAREST: case D3DFILTER_LINEARMIPNEAREST: tex_mag = WINED3DTEXF_POINT; break; case D3DFILTER_LINEAR: + case D3DFILTER_MIPLINEAR: case D3DFILTER_LINEARMIPLINEAR: tex_mag = WINED3DTEXF_LINEAR; break; default: + tex_mag = WINED3DTEXF_POINT; ERR("Unhandled texture mag %d !\n",Value); + break; } hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, @@ -2666,24 +2733,26 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, case D3DRENDERSTATE_TEXTUREMIN: { - WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_POINT; - WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE; + WINED3DTEXTUREFILTERTYPE tex_min; + WINED3DTEXTUREFILTERTYPE tex_mip; switch ((D3DTEXTUREFILTER) Value) { case D3DFILTER_NEAREST: tex_min = WINED3DTEXF_POINT; + tex_mip = WINED3DTEXF_NONE; break; case D3DFILTER_LINEAR: tex_min = WINED3DTEXF_LINEAR; + tex_mip = WINED3DTEXF_NONE; break; case D3DFILTER_MIPNEAREST: tex_min = WINED3DTEXF_POINT; tex_mip = WINED3DTEXF_POINT; break; case D3DFILTER_MIPLINEAR: - tex_min = WINED3DTEXF_POINT; - tex_mip = WINED3DTEXF_LINEAR; + tex_min = WINED3DTEXF_LINEAR; + tex_mip = WINED3DTEXF_POINT; break; case D3DFILTER_LINEARMIPNEAREST: tex_min = WINED3DTEXF_POINT; @@ -2696,11 +2765,13 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, default: ERR("Unhandled texture min %d !\n",Value); + tex_min = WINED3DTEXF_POINT; + tex_mip = WINED3DTEXF_NONE; + break; } - IWineD3DDevice_SetSamplerState(This->wineD3DDevice, - 0, WINED3DSAMP_MIPFILTER, - tex_mip); + IWineD3DDevice_SetSamplerState(This->wineD3DDevice, + 0, WINED3DSAMP_MIPFILTER, tex_mip); hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, 0, WINED3DSAMP_MINFILTER, tex_min); @@ -2723,9 +2794,22 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, Value); break; - default: + case D3DRENDERSTATE_BORDERCOLOR: + /* This should probably just forward to the corresponding sampler + * state. Needs tests. */ + FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n"); + hr = E_NOTIMPL; + break; - /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */ + default: + if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00 + && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31) + { + FIXME("Unhandled stipple pattern render state (%#x).\n", + RenderStateType); + hr = E_NOTIMPL; + break; + } hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice, RenderStateType, diff --git a/reactos/dll/directx/wine/ddraw/direct3d.c b/reactos/dll/directx/wine/ddraw/direct3d.c index 80052adb83f..3f2410fe8a7 100644 --- a/reactos/dll/directx/wine/ddraw/direct3d.c +++ b/reactos/dll/directx/wine/ddraw/direct3d.c @@ -1273,6 +1273,7 @@ IDirect3DImpl_GetCaps(IWineD3D *WineD3D, /* Copy the results into the d3d7 and d3d3 structures */ Desc7->dwDevCaps = WCaps.DevCaps; + Desc7->dpcLineCaps.dwMiscCaps = WCaps.PrimitiveMiscCaps; Desc7->dpcLineCaps.dwRasterCaps = WCaps.RasterCaps; Desc7->dpcLineCaps.dwZCmpCaps = WCaps.ZCmpCaps; Desc7->dpcLineCaps.dwSrcBlendCaps = WCaps.SrcBlendCaps; diff --git a/reactos/dll/directx/wine/ddraw/executebuffer.c b/reactos/dll/directx/wine/ddraw/executebuffer.c index 2f426881cba..29fd65e25a9 100644 --- a/reactos/dll/directx/wine/ddraw/executebuffer.c +++ b/reactos/dll/directx/wine/ddraw/executebuffer.c @@ -489,7 +489,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX)); } else { - ERR("Unhandled vertex processing !\n"); + ERR("Unhandled vertex processing flag %#x.\n", ci->dwFlags); } instr += size; @@ -703,7 +703,6 @@ IDirect3DExecuteBufferImpl_Lock(IDirect3DExecuteBuffer *iface, TRACE("(%p)->(%p)\n", This, lpDesc); dwSize = lpDesc->dwSize; - memset(lpDesc, 0, dwSize); memcpy(lpDesc, &This->desc, dwSize); if (TRACE_ON(d3d7)) { @@ -789,7 +788,6 @@ IDirect3DExecuteBufferImpl_GetExecuteData(IDirect3DExecuteBuffer *iface, TRACE("(%p)->(%p): stub!\n", This, lpData); dwSize = lpData->dwSize; - memset(lpData, 0, dwSize); memcpy(lpData, &This->data, dwSize); if (TRACE_ON(d3d7)) { diff --git a/reactos/dll/directx/wine/ddraw/main.c b/reactos/dll/directx/wine/ddraw/main.c index bc23987ed81..72426cdf26c 100644 --- a/reactos/dll/directx/wine/ddraw/main.c +++ b/reactos/dll/directx/wine/ddraw/main.c @@ -288,7 +288,7 @@ err_out: /* Let's hope we never need this ;) */ if(wineD3DDevice) IWineD3DDevice_Release(wineD3DDevice); if(wineD3D) IWineD3D_Release(wineD3D); - if(This) HeapFree(GetProcessHeap(), 0, This->decls); + HeapFree(GetProcessHeap(), 0, This->decls); HeapFree(GetProcessHeap(), 0, This); return hr; } diff --git a/reactos/dll/directx/wine/ddraw/material.c b/reactos/dll/directx/wine/ddraw/material.c index 6f162f7c828..d75501ecd95 100644 --- a/reactos/dll/directx/wine/ddraw/material.c +++ b/reactos/dll/directx/wine/ddraw/material.c @@ -294,7 +294,6 @@ IDirect3DMaterialImpl_GetMaterial(IDirect3DMaterial3 *iface, /* Copies the material structure */ EnterCriticalSection(&ddraw_cs); dwSize = lpMat->dwSize; - memset(lpMat, 0, dwSize); memcpy(lpMat, &This->mat, dwSize); LeaveCriticalSection(&ddraw_cs); diff --git a/reactos/dll/directx/wine/ddraw/utils.c b/reactos/dll/directx/wine/ddraw/utils.c index cfb04049770..5166b167b4a 100644 --- a/reactos/dll/directx/wine/ddraw/utils.c +++ b/reactos/dll/directx/wine/ddraw/utils.c @@ -171,7 +171,7 @@ PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, DDPixelFormat->u2.dwRBitMask = 0x00E0; DDPixelFormat->u3.dwGBitMask = 0x001C; DDPixelFormat->u4.dwBBitMask = 0x0003; - DDPixelFormat->u5.dwRGBAlphaBitMask = 0xF000; + DDPixelFormat->u5.dwRGBAlphaBitMask = 0xFF00; break; case WINED3DFMT_B4G4R4X4_UNORM: @@ -182,7 +182,7 @@ PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, DDPixelFormat->u3.dwGBitMask = 0x00F0; DDPixelFormat->u4.dwBBitMask = 0x000F; DDPixelFormat->u5.dwRGBAlphaBitMask = 0x0; - return; + break; /* How are Z buffer bit depth and Stencil buffer bit depth related? */ @@ -236,8 +236,8 @@ PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, DDPixelFormat->u3.dwZBitMask = 0x00FFFFFFFF; DDPixelFormat->u4.dwStencilBitMask = 0x00000000; DDPixelFormat->u5.dwRGBAlphaBitMask = 0x0; - break; + case WINED3DFMT_S1_UINT_D15_UNORM: DDPixelFormat->dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER; DDPixelFormat->dwFourCC = 0; diff --git a/reactos/dll/directx/wine/wined3d/arb_program_shader.c b/reactos/dll/directx/wine/wined3d/arb_program_shader.c index cf7638605eb..0824fedb571 100644 --- a/reactos/dll/directx/wine/wined3d/arb_program_shader.c +++ b/reactos/dll/directx/wine/wined3d/arb_program_shader.c @@ -39,8 +39,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); WINE_DECLARE_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) - /* Extract a line. Note that this modifies the source string. */ static char *get_line(char **ptr) { @@ -61,14 +59,14 @@ static char *get_line(char **ptr) static void shader_arb_dump_program_source(const char *source) { - unsigned long source_size; + ULONG source_size; char *ptr, *line, *tmp; source_size = strlen(source) + 1; tmp = HeapAlloc(GetProcessHeap(), 0, source_size); if (!tmp) { - ERR("Failed to allocate %lu bytes for shader source.\n", source_size); + ERR("Failed to allocate %u bytes for shader source.\n", source_size); return; } memcpy(tmp, source, source_size); @@ -81,10 +79,13 @@ static void shader_arb_dump_program_source(const char *source) } /* GL locking for state handlers is done by the caller. */ -static BOOL need_mova_const(IWineD3DBaseShader *shader, const struct wined3d_gl_info *gl_info) +static BOOL need_rel_addr_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info) { - IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) shader; - if(!This->baseShader.reg_maps.usesmova) return FALSE; + if (shader->baseShader.reg_maps.shader_version.type == WINED3D_SHADER_TYPE_VERTEX) + { + if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) return TRUE; + } + if (!shader->baseShader.reg_maps.usesmova) return FALSE; return !gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]; } @@ -95,29 +96,85 @@ static inline BOOL use_nv_clip(const struct wined3d_gl_info *gl_info) && !(gl_info->quirks & WINED3D_QUIRK_NV_CLIP_BROKEN); } -static BOOL need_helper_const(const struct wined3d_gl_info *gl_info) +static BOOL need_helper_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info) { - if (!gl_info->supported[NV_VERTEX_PROGRAM] /* Need to init colors. */ - || gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT /* Load the immval offset. */ - || gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W /* Have to init texcoords. */ - || (!use_nv_clip(gl_info)) /* Init the clip texcoord */) - { - return TRUE; - } + if (need_rel_addr_const(shader, gl_info)) return TRUE; + if (!gl_info->supported[NV_VERTEX_PROGRAM]) return TRUE; /* Need to init colors. */ + if (gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT) return TRUE; /* Load the immval offset. */ + if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) return TRUE; /* Have to init texcoords. */ + if (!use_nv_clip(gl_info)) return TRUE; /* Init the clip texcoord */ + if (shader->baseShader.reg_maps.usesnrm) return TRUE; /* 0.0 */ + if (shader->baseShader.reg_maps.usesrcp) return TRUE; /* EPS */ return FALSE; } -static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const struct wined3d_gl_info *gl_info) +static unsigned int reserved_vs_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info) { unsigned int ret = 1; /* We use one PARAM for the pos fixup, and in some cases one to load * some immediate values into the shader */ - if(need_helper_const(gl_info)) ret++; - if(need_mova_const(shader, gl_info)) ret++; + if(need_helper_const(shader, gl_info)) ret++; + if(need_rel_addr_const(shader, gl_info)) ret++; return ret; } +enum arb_helper_value +{ + ARB_ZERO, + ARB_ONE, + ARB_TWO, + ARB_0001, + ARB_EPS, + + ARB_VS_REL_OFFSET +}; + +static const char *arb_get_helper_value(enum wined3d_shader_type shader, enum arb_helper_value value) +{ + if (shader == WINED3D_SHADER_TYPE_GEOMETRY) + { + ERR("Geometry shaders are unsupported\n"); + return "bad"; + } + + if (shader == WINED3D_SHADER_TYPE_PIXEL) + { + switch (value) + { + case ARB_ZERO: return "ps_helper_const.x"; + case ARB_ONE: return "ps_helper_const.y"; + case ARB_TWO: return "coefmul.x"; + case ARB_0001: return "helper_const.xxxy"; + case ARB_EPS: return "ps_helper_const.z"; + default: break; + } + } + else + { + switch (value) + { + case ARB_ZERO: return "helper_const.x"; + case ARB_ONE: return "helper_const.y"; + case ARB_TWO: return "helper_const.z"; + case ARB_EPS: return "helper_const.w"; + case ARB_0001: return "helper_const.xxxy"; + case ARB_VS_REL_OFFSET: return "rel_addr_const.y"; + } + } + FIXME("Unmanaged %s shader helper constant requested: %u\n", + shader == WINED3D_SHADER_TYPE_PIXEL ? "pixel" : "vertex", value); + switch (value) + { + case ARB_ZERO: return "0.0"; + case ARB_ONE: return "1.0"; + case ARB_TWO: return "2.0"; + case ARB_0001: return "{0.0, 0.0, 0.0, 1.0}"; + case ARB_EPS: return "1e-8"; + default: return "bad"; + } +} + static inline BOOL ffp_clip_emul(IWineD3DStateBlockImpl *stateblock) { return stateblock->lowest_disabled_stage < 7; @@ -287,7 +344,8 @@ struct shader_arb_priv const struct arb_ps_compiled_shader *compiled_fprog; const struct arb_vs_compiled_shader *compiled_vprog; GLuint depth_blt_vprogram_id; - GLuint depth_blt_fprogram_id[tex_type_count]; + GLuint depth_blt_fprogram_id_full[tex_type_count]; + GLuint depth_blt_fprogram_id_masked[tex_type_count]; BOOL use_arbfp_fixed_func; struct wine_rb_tree fragment_shaders; BOOL last_ps_const_clamped; @@ -509,7 +567,7 @@ static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl) */ float val[4]; val[0] = context->render_offscreen ? 0.0f - : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height; + : deviceImpl->render_targets[0]->currentDesc.Height; val[1] = context->render_offscreen ? 1.0f : -1.0f; val[2] = 1.0f; val[3] = 0.0f; @@ -576,7 +634,7 @@ static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl) /* GL locking is done by the caller (state handler) */ static void shader_arb_load_constants(const struct wined3d_context *context, char usePixelShader, char useVertexShader) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; + IWineD3DDeviceImpl *device = context->swapchain->device; IWineD3DStateBlockImpl* stateBlock = device->stateBlock; const struct wined3d_gl_info *gl_info = context->gl_info; @@ -606,7 +664,7 @@ static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active * context. On a context switch the old context will be fully dirtified */ - if (!context || ((IWineD3DSurfaceImpl *)context->surface)->resource.device != This) return; + if (!context || context->swapchain->device != This) return; memset(context->vshader_const_dirty + start, 1, sizeof(*context->vshader_const_dirty) * count); This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count); @@ -619,7 +677,7 @@ static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active * context. On a context switch the old context will be fully dirtified */ - if (!context || ((IWineD3DSurfaceImpl *)context->surface)->resource.device != This) return; + if (!context || context->swapchain->device != This) return; memset(context->pshader_const_dirty + start, 1, sizeof(*context->pshader_const_dirty) * count); This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count); @@ -670,12 +728,23 @@ static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const s if (pshader) { max_constantsF = gl_info->limits.arb_ps_native_constants; + /* 24 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value. */ + if (max_constantsF < 24) + max_constantsF = gl_info->limits.arb_ps_float_constants; } else { + max_constantsF = gl_info->limits.arb_vs_native_constants; + /* 96 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value. + * Also prevents max_constantsF from becoming less than 0 and + * wrapping . */ + if (max_constantsF < 96) + max_constantsF = gl_info->limits.arb_vs_float_constants; + if(This->baseShader.reg_maps.usesrelconstF) { DWORD highest_constf = 0, clip_limit; - max_constantsF = gl_info->limits.arb_vs_native_constants - reserved_vs_const(iface, gl_info); + + max_constantsF -= reserved_vs_const(This, gl_info); max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants); for(i = 0; i < This->baseShader.limits.constant_float; i++) @@ -708,7 +777,6 @@ static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const s { if (ctx->target_version >= NV2) *num_clipplanes = gl_info->limits.clipplanes; else *num_clipplanes = min(gl_info->limits.clipplanes, 4); - max_constantsF = gl_info->limits.arb_vs_native_constants; } } @@ -1355,7 +1423,9 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD if (pshader) { gen_color_correction(buffer, dst_str, ins->dst[0].write_mask, - "one", "coefmul.x", priv->cur_ps_args->super.color_fixup[sampler_idx]); + arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_ONE), + arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_TWO), + priv->cur_ps_args->super.color_fixup[sampler_idx]); } } @@ -1369,6 +1439,8 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in int insert_line; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; + const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE); + const char *two = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_TWO); /* Assume a new line will be added */ insert_line = 1; @@ -1394,13 +1466,13 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in shader_addline(buffer, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg, regstr); break; case WINED3DSPSM_SIGN: - shader_addline(buffer, "MAD T%c, %s, coefmul.x, -one.x;\n", 'A' + tmpreg, regstr); + shader_addline(buffer, "MAD T%c, %s, %s, -%s;\n", 'A' + tmpreg, regstr, two, one); break; case WINED3DSPSM_SIGNNEG: - shader_addline(buffer, "MAD T%c, %s, -coefmul.x, one.x;\n", 'A' + tmpreg, regstr); + shader_addline(buffer, "MAD T%c, %s, %s, %s;\n", 'A' + tmpreg, regstr, two, one); break; case WINED3DSPSM_COMP: - shader_addline(buffer, "SUB T%c, one.x, %s;\n", 'A' + tmpreg, regstr); + shader_addline(buffer, "SUB T%c, %s, %s;\n", 'A' + tmpreg, one, regstr); break; case WINED3DSPSM_X2: shader_addline(buffer, "ADD T%c, %s, %s;\n", 'A' + tmpreg, regstr, regstr); @@ -1671,12 +1743,16 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins) IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; BOOL pshader = shader_is_pshader_version(shader->baseShader.reg_maps.shader_version.type); struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; + const char *zero = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_ZERO); + const char *one = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_ONE); + const char *two = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_TWO); struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char src0_param[256]; if(ins->handler_idx == WINED3DSIH_MOVA) { char write_mask[6]; + const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET); if(ctx->target_version >= NV2) { shader_hw_map2gl(ins); @@ -1695,15 +1771,15 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins) * The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into * A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign. */ - shader_addline(buffer, "SGE A0_SHADOW%s, %s, mova_const.y;\n", write_mask, src0_param); - shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, mova_const.z, -mova_const.w;\n", write_mask); + shader_addline(buffer, "SGE A0_SHADOW%s, %s, %s;\n", write_mask, src0_param, zero); + shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, %s, -%s;\n", write_mask, two, one); shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param); - shader_addline(buffer, "ADD TA%s, TA, mova_const.x;\n", write_mask); + shader_addline(buffer, "ADD TA%s, TA, rel_addr_const.x;\n", write_mask); shader_addline(buffer, "FLR TA%s, TA;\n", write_mask); if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) { - shader_addline(buffer, "ADD TA%s, TA, helper_const.z;\n", write_mask); + shader_addline(buffer, "ADD TA%s, TA, %s;\n", write_mask, offset); } shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask); @@ -1715,8 +1791,9 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins) src0_param[0] = '\0'; if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) { + const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param); - shader_addline(buffer, "ADD TA.x, %s, helper_const.z;\n", src0_param); + shader_addline(buffer, "ADD TA.x, %s, %s;\n", src0_param, offset); shader_addline(buffer, "ARL A0.x, TA.x;\n"); } else @@ -2170,6 +2247,8 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) const struct wined3d_shader_dst_param *dst = &ins->dst[0]; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; + const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO); + const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE); /* texdepth has an implicit destination, the fragment depth value. It's only parameter, * which is essentially an input, is the destination register because it is the first @@ -2181,7 +2260,7 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) /* According to the msdn, the source register(must be r5) is unusable after * the texdepth instruction, so we're free to modify it */ - shader_addline(buffer, "MIN %s.y, %s.y, one.y;\n", dst_name, dst_name); + shader_addline(buffer, "MIN %s.y, %s.y, %s;\n", dst_name, dst_name, one); /* How to deal with the special case dst_name.g == 0? if r != 0, then * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct @@ -2189,8 +2268,8 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) */ shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name); shader_addline(buffer, "MUL TA.x, %s.x, %s.y;\n", dst_name, dst_name); - shader_addline(buffer, "MIN TA.x, TA.x, one.x;\n"); - shader_addline(buffer, "MAX result.depth, TA.x, 0.0;\n"); + shader_addline(buffer, "MIN TA.x, TA.x, %s;\n", one); + shader_addline(buffer, "MAX result.depth, TA.x, %s;\n", zero); } /** Process the WINED3DSIO_TEXDP3TEX instruction in ARB: @@ -2254,6 +2333,8 @@ static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins const struct wined3d_shader_dst_param *dst = &ins->dst[0]; char src0[50], dst_name[50]; BOOL is_color; + const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO); + const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE); shader_arb_get_src_param(ins, &ins->src[0], 0, src0); shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color); @@ -2265,8 +2346,8 @@ static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins */ shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name); shader_addline(buffer, "MUL %s.x, %s.x, %s.y;\n", dst_name, dst_name, dst_name); - shader_addline(buffer, "MIN %s.x, %s.x, one.x;\n", dst_name, dst_name); - shader_addline(buffer, "MAX result.depth, %s.x, 0.0;\n", dst_name); + shader_addline(buffer, "MIN %s.x, %s.x, %s;\n", dst_name, dst_name, one); + shader_addline(buffer, "MAX result.depth, %s.x, %s;\n", dst_name, zero); } /** Handles transforming all WINED3DSIO_M?x? opcodes for @@ -2325,6 +2406,44 @@ static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins) } } +static void shader_hw_rcp(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + const char *flt_eps = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_EPS); + + char dst[50]; + char src[50]; + + shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */ + shader_arb_get_src_param(ins, &ins->src[0], 0, src); + if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE) + { + /* Dx sdk says .x is used if no swizzle is given, but our test shows that + * .w is used + */ + strcat(src, ".w"); + } + + /* TODO: If the destination is readable, and not the same as the source, the destination + * can be used instead of TA + */ + if (priv->target_version >= NV2) + { + shader_addline(buffer, "MOVC TA.x, %s;\n", src); + shader_addline(buffer, "MOV TA.x (EQ.x), %s;\n", flt_eps); + shader_addline(buffer, "RCP%s %s, TA.x;\n", shader_arb_get_modifier(ins), dst); + } + else + { + const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO); + shader_addline(buffer, "ABS TA.x, %s;\n", src); + shader_addline(buffer, "SGE TA.y, -TA.x, %s;\n", zero); + shader_addline(buffer, "MAD TA.x, TA.y, %s, %s;\n", flt_eps, src); + shader_addline(buffer, "RCP%s %s, TA.x;\n", shader_arb_get_modifier(ins), dst); + } +} + static void shader_hw_scalar_op(const struct wined3d_shader_instruction *ins) { struct wined3d_shader_buffer *buffer = ins->ctx->buffer; @@ -2364,20 +2483,44 @@ static void shader_hw_nrm(const struct wined3d_shader_instruction *ins) char src_name[50]; struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type); + const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO); shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); shader_arb_get_src_param(ins, &ins->src[0], 1 /* Use TB */, src_name); + /* In D3D, NRM of a vector with length zero returns zero. Catch this situation, as + * otherwise NRM or RSQ would return NaN */ if(pshader && priv->target_version >= NV3) { + /* GL_NV_fragment_program2's NRM needs protection against length zero vectors too + * + * TODO: Find out if DP3+NRM+MOV is really faster than DP3+RSQ+MUL + */ + shader_addline(buffer, "DP3C TA, %s, %s;\n", src_name, src_name); shader_addline(buffer, "NRM%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name); + shader_addline(buffer, "MOV %s (EQ), %s;\n", dst_name, zero); + } + else if(priv->target_version >= NV2) + { + shader_addline(buffer, "DP3C TA.x, %s, %s;\n", src_name, src_name); + shader_addline(buffer, "RSQ TA.x (NE), TA.x;\n"); + shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name, + src_name); } else { - shader_addline(buffer, "DP3 TA, %s, %s;\n", src_name, src_name); - shader_addline(buffer, "RSQ TA, TA.x;\n"); + const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE); + + shader_addline(buffer, "DP3 TA.x, %s, %s;\n", src_name, src_name); + /* Pass any non-zero value to RSQ if the input vector has a length of zero. The + * RSQ result doesn't matter, as long as multiplying it by 0 returns 0. + */ + shader_addline(buffer, "SGE TA.y, -TA.x, %s;\n", zero); + shader_addline(buffer, "MAD TA.x, %s, TA.y, TA.x;\n", one); + + shader_addline(buffer, "RSQ TA.x, TA.x;\n"); /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/ - shader_addline(buffer, "MUL%s %s, %s, TA;\n", shader_arb_get_modifier(ins), dst_name, + shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name, src_name); } } @@ -2997,6 +3140,7 @@ static void vshader_add_footer(IWineD3DVertexShaderImpl *This, struct wined3d_sh { unsigned int cur_clip = 0; char component[4] = {'x', 'y', 'z', 'w'}; + const char *zero = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ZERO); for (i = 0; i < gl_info->limits.clipplanes; ++i) { @@ -3009,16 +3153,16 @@ static void vshader_add_footer(IWineD3DVertexShaderImpl *This, struct wined3d_sh switch(cur_clip) { case 0: - shader_addline(buffer, "MOV TA, -helper_const.w;\n"); + shader_addline(buffer, "MOV TA, %s;\n", zero); break; case 1: - shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n"); + shader_addline(buffer, "MOV TA.yzw, %s;\n", zero); break; case 2: - shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n"); + shader_addline(buffer, "MOV TA.zw, %s;\n", zero); break; case 3: - shader_addline(buffer, "MOV TA.w, -helper_const.w;\n"); + shader_addline(buffer, "MOV TA.w, %s;\n", zero); break; } shader_addline(buffer, "MOV result.texcoord[%u], TA;\n", @@ -3028,8 +3172,9 @@ static void vshader_add_footer(IWineD3DVertexShaderImpl *This, struct wined3d_sh /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c * and the glsl equivalent */ - if(need_helper_const(gl_info)) { - shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); + if(need_helper_const((IWineD3DBaseShaderImpl *) This, gl_info)) { + const char *two = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_TWO); + shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, %s, -TMP_OUT.w;\n", two); } else { shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n"); shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n"); @@ -3103,18 +3248,50 @@ static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_inf } /* GL locking is done by the caller */ -static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) +static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info, + enum tex_types tex_type, BOOL masked) { GLuint program_id = 0; + const char *fprogram; GLint pos; - static const char * const blt_fprograms[tex_type_count] = + static const char * const blt_fprograms_full[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_rect */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + }; + + static const char * const blt_fprograms_masked[tex_type_count] = { /* tex_1d */ NULL, /* tex_2d */ "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n" "MOV result.depth.z, R0.x;\n" "END\n", @@ -3122,28 +3299,37 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i NULL, /* tex_cube */ "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n" "MOV result.depth.z, R0.x;\n" "END\n", /* tex_rect */ "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n" "MOV result.depth.z, R0.x;\n" "END\n", }; - if (!blt_fprograms[tex_type]) + fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type]; + if (!fprogram) { - FIXME("tex_type %#x not supported\n", tex_type); + FIXME("tex_type %#x not supported, falling back to tex_2d\n", tex_type); tex_type = tex_2d; + fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type]; } GL_EXTCALL(glGenProgramsARB(1, &program_id)); GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id)); - GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(blt_fprograms[tex_type]), blt_fprograms[tex_type])); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fprogram), fprogram)); checkGLcall("glProgramStringARB()"); glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); @@ -3151,7 +3337,7 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i { FIXME("Fragment program error at position %d: %s\n\n", pos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); - shader_arb_dump_program_source(blt_fprograms[tex_type]); + shader_arb_dump_program_source(fprogram); } else { @@ -3309,7 +3495,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct char fragcolor[16]; DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This), next_local, cur; struct shader_arb_ctx_priv priv_ctx; - BOOL dcl_tmp = args->super.srgb_correction, dcl_td = FALSE; + BOOL dcl_td = FALSE; BOOL want_nv_prog = FALSE; struct arb_pshader_private *shader_priv = This->baseShader.backend_data; GLint errPos; @@ -3331,7 +3517,6 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct } switch(found) { - case 4: dcl_tmp = FALSE; break; case 0: sprintf(srgbtmp[0], "TA"); sprintf(srgbtmp[1], "TB"); @@ -3351,6 +3536,8 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct case 3: sprintf(srgbtmp[3], "TA"); break; + case 4: + break; } /* Create the hw ARB shader */ @@ -3432,7 +3619,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */ shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n"); shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n"); - shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n"); + shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %1.10f, 0.0 };\n", eps); if (reg_maps->shader_version.major < 2) { @@ -3927,11 +4114,11 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, struct } shader_addline(buffer, "TEMP TMP_OUT;\n"); - if(need_helper_const(gl_info)) { - shader_addline(buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset); + if(need_helper_const((IWineD3DBaseShaderImpl *) This, gl_info)) { + shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %1.10f};\n", eps); } - if(need_mova_const((IWineD3DBaseShader *) This, gl_info)) { - shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n"); + if(need_rel_addr_const((IWineD3DBaseShaderImpl *) This, gl_info)) { + shader_addline(buffer, "PARAM rel_addr_const = { 0.5, %d.0, 0.0, 0.0 };\n", This->rel_offset); shader_addline(buffer, "TEMP A0_SHADOW;\n"); } @@ -3979,15 +4166,18 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, struct */ if (!gl_info->supported[NV_VERTEX_PROGRAM]) { - shader_addline(buffer, "MOV result.color.secondary, -helper_const.wwwy;\n"); + const char *color_init = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_0001); + shader_addline(buffer, "MOV result.color.secondary, %s;\n", color_init); if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !device->frag_pipe->ffp_proj_control) { int i; - for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) { - if(This->baseShader.reg_maps.texcoord_mask[i] != 0 && + const char *one = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ONE); + for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) + { + if (This->baseShader.reg_maps.texcoord_mask[i] != 0 && This->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) { - shader_addline(buffer, "MOV result.texcoord[%u].w, -helper_const.y;\n", i); + shader_addline(buffer, "MOV result.texcoord[%u].w, %s\n", i, one); } } } @@ -4339,7 +4529,7 @@ static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IW /* GL locking is done by the caller */ static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) { - IWineD3DDeviceImpl *This = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; + IWineD3DDeviceImpl *This = context->swapchain->device; struct shader_arb_priv *priv = This->shader_priv; const struct wined3d_gl_info *gl_info = context->gl_info; int i; @@ -4443,18 +4633,23 @@ static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, } /* GL locking is done by the caller */ -static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { +static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size) +{ + const float mask[] = {0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy}; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + BOOL masked = ds_mask_size->cx && ds_mask_size->cy; struct shader_arb_priv *priv = This->shader_priv; - GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type]; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + GLuint *blt_fprogram; if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info); GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id)); glEnable(GL_VERTEX_PROGRAM_ARB); - if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type); + blt_fprogram = masked ? &priv->depth_blt_fprogram_id_masked[tex_type] : &priv->depth_blt_fprogram_id_full[tex_type]; + if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type, masked); GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram)); + if (masked) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, mask)); glEnable(GL_FRAGMENT_PROGRAM_ARB); } @@ -4499,7 +4694,7 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { if (shader_data->num_gl_shaders) { - struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(device, NULL); ENTER_GL(); for (i = 0; i < shader_data->num_gl_shaders; ++i) @@ -4525,7 +4720,7 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { if (shader_data->num_gl_shaders) { - struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(device, NULL); ENTER_GL(); for (i = 0; i < shader_data->num_gl_shaders; ++i) @@ -4594,9 +4789,15 @@ static void shader_arb_free(IWineD3DDevice *iface) { if(priv->depth_blt_vprogram_id) { GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id)); } - for (i = 0; i < tex_type_count; ++i) { - if (priv->depth_blt_fprogram_id[i]) { - GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i])); + for (i = 0; i < tex_type_count; ++i) + { + if (priv->depth_blt_fprogram_id_full[i]) + { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_full[i])); + } + if (priv->depth_blt_fprogram_id_masked[i]) + { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_masked[i])); } } LEAVE_GL(); @@ -4611,16 +4812,19 @@ static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) { static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *pCaps) { - DWORD vs_consts = min(gl_info->limits.arb_vs_float_constants, gl_info->limits.arb_vs_native_constants); - DWORD ps_consts = min(gl_info->limits.arb_ps_float_constants, gl_info->limits.arb_ps_native_constants); - - /* We don't have an ARB fixed function pipeline yet, so let the none backend set its caps, - * then overwrite the shader specific ones - */ - none_shader_backend.shader_get_caps(gl_info, pCaps); - if (gl_info->supported[ARB_VERTEX_PROGRAM]) { + DWORD vs_consts; + + /* 96 is the minimum allowed value of MAX_PROGRAM_ENV_PARAMETERS_ARB + * for vertex programs. If the native limit is less than that it's + * not very useful, and e.g. Mesa swrast returns 0, probably to + * indicate it's a software implementation. */ + if (gl_info->limits.arb_vs_native_constants < 96) + vs_consts = gl_info->limits.arb_vs_float_constants; + else + vs_consts = min(gl_info->limits.arb_vs_float_constants, gl_info->limits.arb_vs_native_constants); + if (gl_info->supported[NV_VERTEX_PROGRAM3]) { pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); @@ -4639,9 +4843,23 @@ static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct sh } pCaps->MaxVertexShaderConst = vs_consts; } + else + { + pCaps->VertexShaderVersion = 0; + pCaps->MaxVertexShaderConst = 0; + } if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) { + DWORD ps_consts; + + /* Similar as above for vertex programs, but the minimum for fragment + * programs is 24. */ + if (gl_info->limits.arb_ps_native_constants < 24) + ps_consts = gl_info->limits.arb_ps_float_constants; + else + ps_consts = min(gl_info->limits.arb_ps_float_constants, gl_info->limits.arb_ps_native_constants); + if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) { pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); @@ -4661,6 +4879,12 @@ static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct sh pCaps->PixelShader1xMaxValue = 8.0f; pCaps->MaxPixelShaderConst = ps_consts; } + else + { + pCaps->PixelShaderVersion = 0; + pCaps->PixelShader1xMaxValue = 0.0f; + pCaps->MaxPixelShaderConst = 0; + } pCaps->VSClipping = use_nv_clip(gl_info); } @@ -4766,7 +4990,7 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_NRM */ shader_hw_nrm, /* WINED3DSIH_PHASE */ NULL, /* WINED3DSIH_POW */ shader_hw_log_pow, - /* WINED3DSIH_RCP */ shader_hw_scalar_op, + /* WINED3DSIH_RCP */ shader_hw_rcp, /* WINED3DSIH_REP */ shader_hw_rep, /* WINED3DSIH_RET */ shader_hw_ret, /* WINED3DSIH_RSQ */ shader_hw_scalar_op, @@ -5279,6 +5503,7 @@ static void arbfp_free(IWineD3DDevice *iface) { static void arbfp_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) { + caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP; caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | WINED3DTEXOPCAPS_SELECTARG1 | WINED3DTEXOPCAPS_SELECTARG2 | @@ -5309,14 +5534,11 @@ static void arbfp_get_caps(const struct wined3d_gl_info *gl_info, struct fragmen caps->MaxTextureBlendStages = 8; caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8); - - caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; } -#undef GLINFO_LOCATION -#define GLINFO_LOCATION stateblock->device->adapter->gl_info static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *device = stateblock->device; float col[4]; @@ -5338,6 +5560,7 @@ static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *statebloc static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *device = stateblock->device; float col[4]; @@ -5366,6 +5589,7 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *device = stateblock->device; float mat[2][2]; @@ -5377,9 +5601,8 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, s /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled * anyway */ - if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) { - device->StateTable[STATE_PIXELSHADERCONSTANT].apply(STATE_PIXELSHADERCONSTANT, stateblock, context); - } + if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) + stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context); } if(device->shader_backend == &arb_program_shader_backend) { @@ -5403,6 +5626,7 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, s static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *device = stateblock->device; float param[4]; @@ -5414,9 +5638,8 @@ static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock /* The pixel shader has to know the luminance offset. Do a constants update if it * isn't scheduled anyway */ - if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) { - device->StateTable[STATE_PIXELSHADERCONSTANT].apply(STATE_PIXELSHADERCONSTANT, stateblock, context); - } + if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) + stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context); } if(device->shader_backend == &arb_program_shader_backend) { @@ -5648,9 +5871,9 @@ static void gen_ffp_instr(struct wined3d_shader_buffer *buffer, unsigned int sta } } -/* The stateblock is passed for GLINFO_LOCATION */ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWineD3DStateBlockImpl *stateblock) { + const struct wined3d_gl_info *gl_info = &stateblock->device->adapter->gl_info; unsigned int stage; struct wined3d_shader_buffer buffer; BOOL tex_read[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; @@ -5925,6 +6148,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *device = stateblock->device; struct shader_arb_priv *priv = device->fragment_priv; BOOL use_pshader = use_ps(stateblock); @@ -5961,7 +6185,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, return; } new_desc->num_textures_used = 0; - for (i = 0; i < context->gl_info->limits.texture_stages; ++i) + for (i = 0; i < gl_info->limits.texture_stages; ++i) { if(settings.op[i].cop == WINED3DTOP_DISABLE) break; new_desc->num_textures_used = i; @@ -6007,13 +6231,10 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { device->shader_backend->shader_select(context, use_pshader, use_vshader); - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { - device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context); - } - } - if(use_pshader) { - device->StateTable[STATE_PIXELSHADERCONSTANT].apply(STATE_PIXELSHADERCONSTANT, stateblock, context); + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) + stateblock_apply_state(STATE_VERTEXSHADERCONSTANT, stateblock, context); } + if (use_pshader) stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context); } /* We can't link the fog states to the fragment state directly since the vertex pipeline links them @@ -6060,130 +6281,128 @@ static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, struct } } -#undef GLINFO_LOCATION - static const struct StateEntryTemplate arbfp_fragmentstate_template[] = { {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, {STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, {STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, {STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, @@ -6194,11 +6413,11 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] = { {STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, {STATE_PIXELSHADER, { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, @@ -6223,13 +6442,12 @@ const struct fragment_pipeline arbfp_fragment_pipeline = { TRUE /* We can disable projected textures */ }; -#define GLINFO_LOCATION device->adapter->gl_info - struct arbfp_blit_priv { GLenum yuy2_rect_shader, yuy2_2d_shader; GLenum uyvy_rect_shader, uyvy_2d_shader; GLenum yv12_rect_shader, yv12_2d_shader; GLenum p8_rect_shader, p8_2d_shader; + GLuint palette_texture; }; static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) { @@ -6245,6 +6463,7 @@ static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) { /* Context activation is done by the caller. */ static void arbfp_blit_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct arbfp_blit_priv *priv = device->blit_priv; ENTER_GL(); @@ -6257,6 +6476,8 @@ static void arbfp_blit_free(IWineD3DDevice *iface) { GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_rect_shader)); GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_2d_shader)); checkGLcall("Delete yuv and p8 programs"); + + if(priv->palette_texture) glDeleteTextures(1, &priv->palette_texture); LEAVE_GL(); HeapFree(GetProcessHeap(), 0, device->blit_priv); @@ -6499,6 +6720,7 @@ static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, static GLuint gen_p8_shader(IWineD3DDeviceImpl *device, GLenum textype) { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; GLenum shader; struct wined3d_shader_buffer buffer; struct arbfp_blit_priv *priv = device->blit_priv; @@ -6563,9 +6785,43 @@ static GLuint gen_p8_shader(IWineD3DDeviceImpl *device, GLenum textype) return shader; } +/* Context activation is done by the caller. */ +static void upload_palette(IWineD3DSurfaceImpl *surface) +{ + BYTE table[256][4]; + IWineD3DDeviceImpl *device = surface->resource.device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct arbfp_blit_priv *priv = device->blit_priv; + BOOL colorkey = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) ? TRUE : FALSE; + + d3dfmt_p8_init_palette(surface, table, colorkey); + + ENTER_GL(); + if (!priv->palette_texture) + glGenTextures(1, &priv->palette_texture); + + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1)); + glBindTexture(GL_TEXTURE_1D, priv->palette_texture); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + /* Make sure we have discrete color levels. */ + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + /* Upload the palette */ + /* TODO: avoid unneeed uploads in the future by adding some SFLAG_PALETTE_DIRTY mechanism */ + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table); + + /* Switch back to unit 0 in which the 2D texture will be stored. */ + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0)); + LEAVE_GL(); +} + /* Context activation is done by the caller. */ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum complex_fixup yuv_fixup, GLenum textype) { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; GLenum shader; struct wined3d_shader_buffer buffer; char luminance_component; @@ -6720,19 +6976,20 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum complex_fixup yuv_ } /* Context activation is done by the caller. */ -static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatDesc *format_desc, - GLenum textype, UINT width, UINT height) +static HRESULT arbfp_blit_set(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface) { GLenum shader; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; - float size[4] = {width, height, 1, 1}; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + float size[4] = {surface->pow2Width, surface->pow2Height, 1, 1}; struct arbfp_blit_priv *priv = device->blit_priv; enum complex_fixup fixup; + GLenum textype = surface->texture_target; - if (!is_complex_fixup(format_desc->color_fixup)) + if (!is_complex_fixup(surface->resource.format_desc->color_fixup)) { TRACE("Fixup:\n"); - dump_color_fixup_desc(format_desc->color_fixup); + dump_color_fixup_desc(surface->resource.format_desc->color_fixup); /* Don't bother setting up a shader for unconverted formats */ ENTER_GL(); glEnable(textype); @@ -6741,7 +6998,7 @@ static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatD return WINED3D_OK; } - fixup = get_complex_fixup(format_desc->color_fixup); + fixup = get_complex_fixup(surface->resource.format_desc->color_fixup); switch(fixup) { @@ -6760,6 +7017,8 @@ static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatD case COMPLEX_FIXUP_P8: shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->p8_rect_shader : priv->p8_2d_shader; if (!shader) shader = gen_p8_shader(device, textype); + + upload_palette(surface); break; default: @@ -6808,31 +7067,47 @@ static void arbfp_blit_unset(IWineD3DDevice *iface) { LEAVE_GL(); } -static BOOL arbfp_blit_color_fixup_supported(struct color_fixup_desc fixup) +static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, + const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, + const struct wined3d_format_desc *dst_format_desc) { - enum complex_fixup complex_fixup; + enum complex_fixup src_fixup; + + if (blit_op != BLIT_OP_BLIT) + { + TRACE("Unsupported blit_op=%d\n", blit_op); + return FALSE; + } + src_fixup = get_complex_fixup(src_format_desc->color_fixup); if (TRACE_ON(d3d_shader) && TRACE_ON(d3d)) { TRACE("Checking support for fixup:\n"); - dump_color_fixup_desc(fixup); + dump_color_fixup_desc(src_format_desc->color_fixup); } - if (is_identity_fixup(fixup)) + if (!is_identity_fixup(dst_format_desc->color_fixup)) + { + TRACE("Destination fixups are not supported\n"); + return FALSE; + } + + if (is_identity_fixup(src_format_desc->color_fixup)) { TRACE("[OK]\n"); return TRUE; } - /* We only support YUV conversions. */ - if (!is_complex_fixup(fixup)) + /* We only support YUV conversions. */ + if (!is_complex_fixup(src_format_desc->color_fixup)) { TRACE("[FAILED]\n"); return FALSE; } - complex_fixup = get_complex_fixup(fixup); - switch(complex_fixup) + switch(src_fixup) { case COMPLEX_FIXUP_YUY2: case COMPLEX_FIXUP_UYVY: @@ -6842,18 +7117,70 @@ static BOOL arbfp_blit_color_fixup_supported(struct color_fixup_desc fixup) return TRUE; default: - FIXME("Unsupported YUV fixup %#x\n", complex_fixup); + FIXME("Unsupported YUV fixup %#x\n", src_fixup); TRACE("[FAILED]\n"); return FALSE; } } +HRESULT arbfp_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, + IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op, + DWORD Filter) +{ + IWineD3DSwapChainImpl *dst_swapchain; + struct wined3d_context *context; + RECT dst_rect = *dst_rect_in; + + /* Now load the surface */ + surface_internal_preload(src_surface, SRGB_RGB); + + /* Activate the destination context, set it up for blitting */ + context = context_acquire(device, dst_surface); + context_apply_blit_state(context, device); + + /* The coordinates of the ddraw front buffer are always fullscreen ('screen coordinates', + * while OpenGL coordinates are window relative. + * Also beware of the origin difference(top left vs bottom left). + * Also beware that the front buffer's surface size is screen width x screen height, + * whereas the real gl drawable size is the size of the window. */ + dst_swapchain = (dst_surface->Flags & SFLAG_SWAPCHAIN) ? (IWineD3DSwapChainImpl *)dst_surface->container : NULL; + if (dst_swapchain && dst_surface == dst_swapchain->front_buffer) + surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect); + + arbfp_blit_set((IWineD3DDevice *)device, src_surface); + + ENTER_GL(); + + /* Draw a textured quad */ + draw_textured_quad(src_surface, src_rect, &dst_rect, Filter); + + LEAVE_GL(); + + /* Leave the opengl state valid for blitting */ + arbfp_blit_unset((IWineD3DDevice *)device); + + if (wined3d_settings.strict_draw_ordering || (dst_swapchain + && (dst_surface == dst_swapchain->front_buffer + || dst_swapchain->num_contexts > 1))) + wglFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); + + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, TRUE); + return WINED3D_OK; +} + +static HRESULT arbfp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color) +{ + FIXME("Color filling not implemented by arbfp_blit\n"); + return WINED3DERR_INVALIDCALL; +} + const struct blit_shader arbfp_blit = { arbfp_blit_alloc, arbfp_blit_free, arbfp_blit_set, arbfp_blit_unset, - arbfp_blit_color_fixup_supported, + arbfp_blit_supported, + arbfp_blit_color_fill }; - -#undef GLINFO_LOCATION diff --git a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c index 0f911e9dc15..993ece0be8d 100644 --- a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c +++ b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -190,7 +190,6 @@ static const char *debug_mask(GLuint mask) { default: return "Unexpected writemask"; } } -#define GLINFO_LOCATION (*gl_info) static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) @@ -796,11 +795,10 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())"); return ret; } -#undef GLINFO_LOCATION -#define GLINFO_LOCATION stateblock->device->adapter->gl_info static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; IWineD3DDeviceImpl *This = stateblock->device; const struct atifs_ffp_desc *desc; struct ffp_frag_settings settings; @@ -818,14 +816,14 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, st return; } new_desc->num_textures_used = 0; - for (i = 0; i < context->gl_info->limits.texture_stages; ++i) + for (i = 0; i < gl_info->limits.texture_stages; ++i) { if(settings.op[i].cop == WINED3DTOP_DISABLE) break; new_desc->num_textures_used = i; } memcpy(&new_desc->parent.settings, &settings, sizeof(settings)); - new_desc->shader = gen_ati_shader(settings.op, context->gl_info); + new_desc->shader = gen_ati_shader(settings.op, gl_info); add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent); TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc); desc = new_desc; @@ -849,6 +847,7 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, st static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); @@ -859,6 +858,7 @@ static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *statebloc static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + const struct wined3d_gl_info *gl_info = context->gl_info; float mat[2][2]; mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); @@ -907,127 +907,124 @@ static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *statebl if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { device->shader_backend->shader_select(context, FALSE, use_vshader); - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) { - device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context); - } + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) + stateblock_apply_state(STATE_VERTEXSHADERCONSTANT, stateblock, context); } } -#undef GLINFO_LOCATION - static const struct StateEntryTemplate atifs_fragmentstate_template[] = { {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, - {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, - {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, @@ -1063,6 +1060,7 @@ static void atifs_enable(IWineD3DDevice *iface, BOOL enable) { static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) { + caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP; caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | WINED3DTEXOPCAPS_SELECTARG1 | WINED3DTEXOPCAPS_SELECTARG2 | @@ -1105,8 +1103,6 @@ static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragmen */ caps->MaxTextureBlendStages = 8; caps->MaxSimultaneousTextures = 6; - - caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; } static HRESULT atifs_alloc(IWineD3DDevice *iface) { @@ -1128,11 +1124,11 @@ static HRESULT atifs_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } -#define GLINFO_LOCATION This->adapter->gl_info /* Context activation is done by the caller. */ static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context) { IWineD3DDeviceImpl *This = context; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry); ENTER_GL(); @@ -1152,7 +1148,6 @@ static void atifs_free(IWineD3DDevice *iface) { HeapFree(GetProcessHeap(), 0, priv); This->fragment_priv = NULL; } -#undef GLINFO_LOCATION static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup) { diff --git a/reactos/dll/directx/wine/wined3d/basetexture.c b/reactos/dll/directx/wine/wined3d/basetexture.c index f3c3fe74e1b..deab4fb2362 100644 --- a/reactos/dll/directx/wine/wined3d/basetexture.c +++ b/reactos/dll/directx/wine/wined3d/basetexture.c @@ -27,9 +27,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); -HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type, - IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, - WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) +HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT layer_count, UINT level_count, + WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage, + const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent, + const struct wined3d_parent_ops *parent_ops) { HRESULT hr; @@ -41,7 +42,17 @@ HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DR return hr; } - texture->baseTexture.levels = levels; + texture->baseTexture.sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + level_count * layer_count * sizeof(*texture->baseTexture.sub_resources)); + if (!texture->baseTexture.sub_resources) + { + ERR("Failed to allocate sub-resource array.\n"); + resource_cleanup((IWineD3DResource *)texture); + return E_OUTOFMEMORY; + } + + texture->baseTexture.layer_count = layer_count; + texture->baseTexture.level_count = level_count; texture->baseTexture.filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; texture->baseTexture.LOD = 0; texture->baseTexture.texture_rgb.dirty = TRUE; @@ -66,9 +77,27 @@ HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DR void basetexture_cleanup(IWineD3DBaseTexture *iface) { basetexture_unload(iface); + HeapFree(GetProcessHeap(), 0, ((IWineD3DBaseTextureImpl *)iface)->baseTexture.sub_resources); resource_cleanup((IWineD3DResource *)iface); } +IWineD3DResourceImpl *basetexture_get_sub_resource(IWineD3DBaseTextureImpl *texture, UINT layer, UINT level) +{ + if (layer >= texture->baseTexture.layer_count) + { + WARN("layer %u >= layer_count %u.\n", layer, texture->baseTexture.layer_count); + return NULL; + } + + if (level >= texture->baseTexture.level_count) + { + WARN("level %u >= level_count %u.\n", level, texture->baseTexture.level_count); + return NULL; + } + + return texture->baseTexture.sub_resources[layer * texture->baseTexture.level_count + level]; +} + /* A GL context is provided by the caller */ static void gltexture_delete(struct gl_texture *tex) { @@ -86,7 +115,7 @@ void basetexture_unload(IWineD3DBaseTexture *iface) if (This->baseTexture.texture_rgb.name || This->baseTexture.texture_srgb.name) { - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); } if(This->baseTexture.texture_rgb.name) { @@ -115,8 +144,8 @@ DWORD basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD LODNew) return 0; } - if(LODNew >= This->baseTexture.levels) - LODNew = This->baseTexture.levels - 1; + if (LODNew >= This->baseTexture.level_count) + LODNew = This->baseTexture.level_count - 1; if(This->baseTexture.LOD != LODNew) { This->baseTexture.LOD = LODNew; @@ -145,8 +174,8 @@ DWORD basetexture_get_lod(IWineD3DBaseTexture *iface) DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - TRACE("(%p) : returning %d\n", This, This->baseTexture.levels); - return This->baseTexture.levels; + TRACE("iface %p, returning %u.\n", iface, This->baseTexture.level_count); + return This->baseTexture.level_count; } HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) @@ -164,7 +193,7 @@ HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DT * Or should we delay the applying until the texture is used for drawing? For now, apply * immediately. */ - struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(device, NULL); ENTER_GL(); glBindTexture(textureDimensions, This->baseTexture.texture_rgb.name); @@ -270,9 +299,7 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0; gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1; gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = 0; - gl_tex->states[WINED3DTEXSTA_ELEMENTINDEX] = 0; - gl_tex->states[WINED3DTEXSTA_DMAPOFFSET] = 0; - gl_tex->states[WINED3DTEXSTA_TSSADDRESSW] = WINED3DTADDRESS_WRAP; + gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; IWineD3DBaseTexture_SetDirty(iface, TRUE); isNewTexture = TRUE; @@ -301,10 +328,11 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac * relying on the partial GL_ARB_texture_non_power_of_two emulation with texture rectangles * (ie, do not care for cond_np2 here, just look for GL_TEXTURE_RECTANGLE_ARB) */ - if(textureDimensions != GL_TEXTURE_RECTANGLE_ARB) { - TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1); - glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1); - checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)"); + if (textureDimensions != GL_TEXTURE_RECTANGLE_ARB) + { + TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", This->baseTexture.level_count - 1); + glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.level_count - 1); + checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.level_count)"); } if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) { /* Cubemaps are always set to clamp, regardless of the sampler state. */ @@ -444,17 +472,18 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue); checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ..."); - if(!cond_np2) { - if(gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) { + if (!cond_np2) + { + if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) glValue = This->baseTexture.LOD; - } else if(gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) { - glValue = This->baseTexture.levels - 1; - } else if(gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD) { + else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.level_count) + glValue = This->baseTexture.level_count - 1; + else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD) /* baseTexture.LOD is already clamped in the setter */ glValue = This->baseTexture.LOD; - } else { + else glValue = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]; - } + /* Note that D3DSAMP_MAXMIPLEVEL specifies the biggest mipmap(default 0), while * GL_TEXTURE_MAX_LEVEL specifies the smallest mimap used(default 1000). * So D3DSAMP_MAXMIPLEVEL is the same as GL_TEXTURE_BASE_LEVEL. @@ -488,4 +517,22 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, } gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso; } + + if (!(This->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW) + != !gl_tex->states[WINED3DTEXSTA_SHADOW]) + { + if (This->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW) + { + glTexParameteri(textureDimensions, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); + glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)"); + gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE; + } + else + { + glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)"); + gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE; + } + } } diff --git a/reactos/dll/directx/wine/wined3d/buffer.c b/reactos/dll/directx/wine/wined3d/buffer.c index e22d311beb9..daece20c33d 100644 --- a/reactos/dll/directx/wine/wined3d/buffer.c +++ b/reactos/dll/directx/wine/wined3d/buffer.c @@ -29,8 +29,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->resource.device->adapter->gl_info - #define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */ #define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */ #define VB_MAXFULLCONVERSIONS 5 /* Number of full conversions before we stop converting */ @@ -97,11 +95,29 @@ static inline BOOL buffer_is_fully_dirty(struct wined3d_buffer *This) return FALSE; } +/* Context activation is done by the caller */ +static void delete_gl_buffer(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) +{ + if(!This->buffer_object) return; + + ENTER_GL(); + GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); + checkGLcall("glDeleteBuffersARB"); + LEAVE_GL(); + This->buffer_object = 0; + + if(This->query) + { + wined3d_event_query_destroy(This->query); + This->query = NULL; + } + This->flags &= ~WINED3D_BUFFER_APPLESYNC; +} + /* Context activation is done by the caller. */ -static void buffer_create_buffer_object(struct wined3d_buffer *This) +static void buffer_create_buffer_object(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) { GLenum error, gl_usage; - const struct wined3d_gl_info *gl_info = &This->resource.device->adapter->gl_info; TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", This, debug_d3dusage(This->resource.usage)); @@ -157,6 +173,10 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This) GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)"); This->flags |= WINED3D_BUFFER_FLUSH; + + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)"); + This->flags |= WINED3D_BUFFER_APPLESYNC; } /* No setup is needed here for GL_ARB_map_buffer_range */ } @@ -203,13 +223,7 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This) fail: /* Clean up all vbo init, but continue because we can work without a vbo :-) */ ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur\n"); - if (This->buffer_object) - { - ENTER_GL(); - GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); - LEAVE_GL(); - } - This->buffer_object = 0; + delete_gl_buffer(This, gl_info); buffer_clear_dirty_areas(This); } @@ -258,12 +272,13 @@ static BOOL buffer_process_converted_attribute(struct wined3d_buffer *This, attrib_size = attrib->format_desc->component_count * attrib->format_desc->component_size; for (i = 0; i < attrib_size; ++i) { - if (This->conversion_map[data + i] != conversion_type) + DWORD_PTR idx = (data + i) % This->stride; + if (This->conversion_map[idx] != conversion_type) { - TRACE("Byte %ld in vertex changed\n", i + data); - TRACE("It was type %d, is %d now\n", This->conversion_map[data + i], conversion_type); + TRACE("Byte %ld in vertex changed\n", idx); + TRACE("It was type %d, is %d now\n", This->conversion_map[idx], conversion_type); ret = TRUE; - This->conversion_map[data + i] = conversion_type; + This->conversion_map[idx] = conversion_type; } } @@ -534,7 +549,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This) } /* Context activation is done by the caller. */ -static void buffer_check_buffer_object_size(struct wined3d_buffer *This) +static void buffer_check_buffer_object_size(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) { UINT size = This->conversion_stride ? This->conversion_stride * (This->resource.size / This->stride) : This->resource.size; @@ -550,7 +565,7 @@ static void buffer_check_buffer_object_size(struct wined3d_buffer *This) /* Rescue the data before resizing the buffer object if we do not have our backup copy */ if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) { - buffer_get_sysmem(This); + buffer_get_sysmem(This, gl_info); } ENTER_GL(); @@ -595,7 +610,7 @@ static inline void fixup_transformed_pos(float *p) } /* Context activation is done by the caller. */ -const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer_object) +const BYTE *buffer_get_memory(IWineD3DBuffer *iface, const struct wined3d_gl_info *gl_info, GLuint *buffer_object) { struct wined3d_buffer *This = (struct wined3d_buffer *)iface; @@ -604,19 +619,19 @@ const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer { if (This->flags & WINED3D_BUFFER_CREATEBO) { - buffer_create_buffer_object(This); + buffer_create_buffer_object(This, gl_info); This->flags &= ~WINED3D_BUFFER_CREATEBO; if (This->buffer_object) { *buffer_object = This->buffer_object; - return (const BYTE *)offset; + return NULL; } } - return This->resource.allocatedMemory + offset; + return This->resource.allocatedMemory; } else { - return (const BYTE *)offset; + return NULL; } } @@ -655,7 +670,7 @@ static ULONG STDMETHODCALLTYPE buffer_AddRef(IWineD3DBuffer *iface) } /* Context activation is done by the caller. */ -BYTE *buffer_get_sysmem(struct wined3d_buffer *This) +BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) { /* AllocatedMemory exists if the buffer is double buffered or has no buffer object at all */ if(This->resource.allocatedMemory) return This->resource.allocatedMemory; @@ -682,20 +697,16 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface) IWineD3DDeviceImpl *device = This->resource.device; struct wined3d_context *context; - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); /* Download the buffer, but don't permanently enable double buffering */ if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) { - buffer_get_sysmem(This); + buffer_get_sysmem(This, context->gl_info); This->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER; } - ENTER_GL(); - GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); - checkGLcall("glDeleteBuffersARB"); - LEAVE_GL(); - This->buffer_object = 0; + delete_gl_buffer(This, context->gl_info); This->flags |= WINED3D_BUFFER_CREATEBO; /* Recreate the buffer object next load */ buffer_clear_dirty_areas(This); @@ -766,26 +777,171 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface) return resource_get_priority((IWineD3DResource *)iface); } +/* The caller provides a context and binds the buffer */ +static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info) +{ + enum wined3d_event_query_result ret; + + /* No fencing needs to be done if the app promises not to overwrite + * existing data */ + if(flags & WINED3DLOCK_NOOVERWRITE) return; + if(flags & WINED3DLOCK_DISCARD) + { + ENTER_GL(); + GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage)); + checkGLcall("glBufferDataARB\n"); + LEAVE_GL(); + return; + } + + if(!This->query) + { + TRACE("Creating event query for buffer %p\n", This); + + if (!wined3d_event_query_supported(gl_info)) + { + FIXME("Event queries not supported, dropping async buffer locks.\n"); + goto drop_query; + } + + This->query = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->query)); + if (!This->query) + { + ERR("Failed to allocate event query memory, dropping async buffer locks.\n"); + goto drop_query; + } + + /* Since we don't know about old draws a glFinish is needed once */ + wglFinish(); + return; + } + TRACE("Synchronizing buffer %p\n", This); + ret = wined3d_event_query_finish(This->query, This->resource.device); + switch(ret) + { + case WINED3D_EVENT_QUERY_NOT_STARTED: + case WINED3D_EVENT_QUERY_OK: + /* All done */ + return; + + case WINED3D_EVENT_QUERY_WRONG_THREAD: + WARN("Cannot synchronize buffer lock due to a thread conflict\n"); + goto drop_query; + + default: + ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret); + goto drop_query; + } + +drop_query: + if(This->query) + { + wined3d_event_query_destroy(This->query); + This->query = NULL; + } + + wglFinish(); + ENTER_GL(); + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); + LEAVE_GL(); + This->flags &= ~WINED3D_BUFFER_APPLESYNC; +} + +/* The caller provides a GL context */ +static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags) +{ + BYTE *map; + UINT start = 0, len = 0; + + ENTER_GL(); + GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + checkGLcall("glBindBufferARB"); + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + GLbitfield mapflags; + mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + if (flags & WINED3D_BUFFER_DISCARD) + { + mapflags |= GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT; + } + else if (flags & WINED3D_BUFFER_NOSYNC) + { + mapflags |= GL_MAP_UNSYNCHRONIZED_BIT; + } + map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, + This->resource.size, mapflags)); + checkGLcall("glMapBufferRange"); + } + else + { + if (This->flags & WINED3D_BUFFER_APPLESYNC) + { + DWORD syncflags = 0; + if (flags & WINED3D_BUFFER_DISCARD) syncflags |= WINED3DLOCK_DISCARD; + if (flags & WINED3D_BUFFER_NOSYNC) syncflags |= WINED3DLOCK_NOOVERWRITE; + LEAVE_GL(); + buffer_sync_apple(This, syncflags, gl_info); + ENTER_GL(); + } + map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB)); + checkGLcall("glMapBufferARB"); + } + if (!map) + { + LEAVE_GL(); + ERR("Failed to map opengl buffer\n"); + return; + } + + while(This->modified_areas) + { + This->modified_areas--; + start = This->maps[This->modified_areas].offset; + len = This->maps[This->modified_areas].size; + + memcpy(map + start, This->resource.allocatedMemory + start, len); + + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len)); + checkGLcall("glFlushMappedBufferRange"); + } + else if (This->flags & WINED3D_BUFFER_FLUSH) + { + GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); + checkGLcall("glFlushMappedBufferRangeAPPLE"); + } + } + GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); + checkGLcall("glUnmapBufferARB"); + LEAVE_GL(); +} + static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) { struct wined3d_buffer *This = (struct wined3d_buffer *)iface; IWineD3DDeviceImpl *device = This->resource.device; UINT start = 0, end = 0, len = 0, vertices; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; BOOL decl_changed = FALSE; unsigned int i, j; BYTE *data; + DWORD flags = This->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD); TRACE("iface %p\n", iface); + This->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD); - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); + gl_info = context->gl_info; if (!This->buffer_object) { /* TODO: Make converting independent from VBOs */ if (This->flags & WINED3D_BUFFER_CREATEBO) { - buffer_create_buffer_object(This); + buffer_create_buffer_object(This, gl_info); This->flags &= ~WINED3D_BUFFER_CREATEBO; } else @@ -836,7 +992,20 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) IWineD3DDeviceImpl_MarkStateDirty(device, STATE_STREAMSRC); goto end; } - buffer_check_buffer_object_size(This); + buffer_check_buffer_object_size(This, gl_info); + + /* The declaration changed, reload the whole buffer */ + WARN("Reloading buffer because of decl change\n"); + buffer_clear_dirty_areas(This); + if(!buffer_add_dirty_area(This, 0, 0)) + { + ERR("buffer_add_dirty_area failed, this is not expected\n"); + return; + } + /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application + * cleared for unsynchronized updates + */ + flags = 0; } else { @@ -864,18 +1033,6 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) } } - if (decl_changed) - { - /* The declaration changed, reload the whole buffer */ - WARN("Reloading buffer because of decl change\n"); - buffer_clear_dirty_areas(This); - if(!buffer_add_dirty_area(This, 0, 0)) - { - ERR("buffer_add_dirty_area failed, this is not expected\n"); - return; - } - } - if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) { IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); @@ -896,18 +1053,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) return; } - ENTER_GL(); - GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); - checkGLcall("glBindBufferARB"); - while(This->modified_areas) - { - This->modified_areas--; - start = This->maps[This->modified_areas].offset; - len = This->maps[This->modified_areas].size; - GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, len, This->resource.allocatedMemory + start)); - checkGLcall("glBufferSubDataARB"); - } - LEAVE_GL(); + buffer_direct_upload(This, context->gl_info, flags); context_release(context); return; @@ -915,7 +1061,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) { - buffer_get_sysmem(This); + buffer_get_sysmem(This, gl_info); } /* Now for each vertex in the buffer that needs conversion */ @@ -1033,7 +1179,7 @@ static WINED3DRESOURCETYPE STDMETHODCALLTYPE buffer_GetType(IWineD3DBuffer *ifac /* IWineD3DBuffer methods */ -static DWORD buffer_sanitize_flags(DWORD flags) +static DWORD buffer_sanitize_flags(struct wined3d_buffer *buffer, DWORD flags) { /* Not all flags make sense together, but Windows never returns an error. Catch the * cases that could cause issues */ @@ -1055,6 +1201,11 @@ static DWORD buffer_sanitize_flags(DWORD flags) WARN("WINED3DLOCK_DISCARD and WINED3DLOCK_NOOVERWRITE used together, ignoring\n"); return 0; } + else if (flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE) && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC)) + { + WARN("DISCARD or NOOVERWRITE lock on non-dynamic buffer, ignoring\n"); + return 0; + } return flags; } @@ -1082,10 +1233,11 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, { struct wined3d_buffer *This = (struct wined3d_buffer *)iface; LONG count; + BOOL dirty = buffer_is_dirty(This); TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags); - flags = buffer_sanitize_flags(flags); + flags = buffer_sanitize_flags(This, flags); if (!(flags & WINED3DLOCK_READONLY)) { if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY; @@ -1093,36 +1245,81 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, count = InterlockedIncrement(&This->lock_count); - if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object) + if (This->buffer_object) { - if(count == 1) + if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) { - IWineD3DDeviceImpl *device = This->resource.device; - struct wined3d_context *context; - const struct wined3d_gl_info *gl_info; - - if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) + if(count == 1) { - IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); - } + IWineD3DDeviceImpl *device = This->resource.device; + struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); - gl_info = context->gl_info; - ENTER_GL(); - GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) + { + IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); + } - if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + context = context_acquire(device, NULL); + gl_info = context->gl_info; + ENTER_GL(); + GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + GLbitfield mapflags = buffer_gl_map_flags(flags); + This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, + This->resource.size, mapflags)); + checkGLcall("glMapBufferRange"); + } + else + { + if(This->flags & WINED3D_BUFFER_APPLESYNC) + { + LEAVE_GL(); + buffer_sync_apple(This, flags, gl_info); + ENTER_GL(); + } + This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); + checkGLcall("glMapBufferARB"); + } + LEAVE_GL(); + + if (((DWORD_PTR) This->resource.allocatedMemory) & (RESOURCE_ALIGNMENT - 1)) + { + WARN("Pointer %p is not %u byte aligned, falling back to double buffered operation\n", + This->resource.allocatedMemory, RESOURCE_ALIGNMENT); + + ENTER_GL(); + GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); + checkGLcall("glUnmapBufferARB"); + LEAVE_GL(); + This->resource.allocatedMemory = NULL; + + buffer_get_sysmem(This, gl_info); + TRACE("New pointer is %p\n", This->resource.allocatedMemory); + } + context_release(context); + } + } + else + { + if (dirty) { - GLbitfield mapflags = buffer_gl_map_flags(flags); - This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, - This->resource.size, mapflags)); + if (This->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3DLOCK_NOOVERWRITE)) + { + This->flags &= ~WINED3D_BUFFER_NOSYNC; + } } - else + else if(flags & WINED3DLOCK_NOOVERWRITE) { - This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); + This->flags |= WINED3D_BUFFER_NOSYNC; + } + + if (flags & WINED3DLOCK_DISCARD) + { + This->flags |= WINED3D_BUFFER_DISCARD; } - LEAVE_GL(); - context_release(context); } } @@ -1169,7 +1366,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface) IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); } - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); gl_info = context->gl_info; ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); @@ -1251,7 +1448,7 @@ HRESULT buffer_init(struct wined3d_buffer *buffer, IWineD3DDeviceImpl *device, UINT size, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, GLenum bind_hint, const char *data, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info); HRESULT hr; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; BOOL dynamic_buffer_ok; @@ -1276,7 +1473,8 @@ HRESULT buffer_init(struct wined3d_buffer *buffer, IWineD3DDeviceImpl *device, TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage, debug_d3dformat(buffer->resource.format_desc->format), buffer->resource.allocatedMemory, buffer); - dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; + /* GL_ARB_map_buffer_range is disabled for now due to numerous bugs and no gains */ + dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]; /* Observations show that drawStridedSlow is faster on dynamic VBs than converting + * drawStridedFast (half-life 2 and others). diff --git a/reactos/dll/directx/wine/wined3d/context.c b/reactos/dll/directx/wine/wined3d/context.c index 08789855812..5304af2f408 100644 --- a/reactos/dll/directx/wine/wined3d/context.c +++ b/reactos/dll/directx/wine/wined3d/context.c @@ -28,8 +28,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) - static DWORD wined3d_context_tls_idx; /* FBO helper functions */ @@ -84,19 +82,19 @@ void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fb } /* GL locking is done by the caller */ -static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info) +static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info, GLenum target) { unsigned int i; for (i = 0; i < gl_info->limits.buffers; ++i) { - gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0); + gl_info->fbo_ops.glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0); checkGLcall("glFramebufferTexture2D()"); } - gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + gl_info->fbo_ops.glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); checkGLcall("glFramebufferTexture2D()"); - gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + gl_info->fbo_ops.glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); checkGLcall("glFramebufferTexture2D()"); } @@ -106,7 +104,7 @@ static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo) const struct wined3d_gl_info *gl_info = context->gl_info; context_bind_fbo(context, GL_FRAMEBUFFER, fbo); - context_clean_fbo_attachments(gl_info); + context_clean_fbo_attachments(gl_info, GL_FRAMEBUFFER); context_bind_fbo(context, GL_FRAMEBUFFER, NULL); gl_info->fbo_ops.glDeleteFramebuffers(1, fbo); @@ -114,17 +112,18 @@ static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo) } /* GL locking is done by the caller */ -static void context_apply_attachment_filter_states(IWineD3DSurface *surface) +static void context_apply_attachment_filter_states(IWineD3DSurfaceImpl *surface) { - const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; - IWineD3DDeviceImpl *device = surface_impl->resource.device; IWineD3DBaseTextureImpl *texture_impl; - BOOL update_minfilter = FALSE; - BOOL update_magfilter = FALSE; /* Update base texture states array */ - if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) + if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)surface, + &IID_IWineD3DBaseTexture, (void **)&texture_impl))) { + IWineD3DDeviceImpl *device = surface->resource.device; + BOOL update_minfilter = FALSE; + BOOL update_magfilter = FALSE; + if (texture_impl->baseTexture.texture_rgb.states[WINED3DTEXSTA_MINFILTER] != WINED3DTEXF_POINT || texture_impl->baseTexture.texture_rgb.states[WINED3DTEXSTA_MIPFILTER] != WINED3DTEXF_NONE) { @@ -146,82 +145,85 @@ static void context_apply_attachment_filter_states(IWineD3DSurface *surface) } IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl); - } - - if (update_minfilter || update_magfilter) - { - GLenum target, bind_target; - GLint old_binding; - target = surface_impl->texture_target; - if (target == GL_TEXTURE_2D) + if (update_minfilter || update_magfilter) { - bind_target = GL_TEXTURE_2D; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); - } else if (target == GL_TEXTURE_RECTANGLE_ARB) { - bind_target = GL_TEXTURE_RECTANGLE_ARB; - glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); - } else { - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding); + GLenum target, bind_target; + GLint old_binding; + + target = surface->texture_target; + if (target == GL_TEXTURE_2D) + { + bind_target = GL_TEXTURE_2D; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); + } + else if (target == GL_TEXTURE_RECTANGLE_ARB) + { + bind_target = GL_TEXTURE_RECTANGLE_ARB; + glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); + } + else + { + bind_target = GL_TEXTURE_CUBE_MAP_ARB; + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding); + } + + glBindTexture(bind_target, surface->texture_name); + if (update_minfilter) glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (update_magfilter) glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(bind_target, old_binding); } - glBindTexture(bind_target, surface_impl->texture_name); - if (update_minfilter) glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - if (update_magfilter) glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(bind_target, old_binding); + checkGLcall("apply_attachment_filter_states()"); } - - checkGLcall("apply_attachment_filter_states()"); } /* GL locking is done by the caller */ void context_attach_depth_stencil_fbo(struct wined3d_context *context, - GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) + GLenum fbo_target, IWineD3DSurfaceImpl *depth_stencil, BOOL use_render_buffer) { - IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil; const struct wined3d_gl_info *gl_info = context->gl_info; TRACE("Attach depth stencil %p\n", depth_stencil); if (depth_stencil) { - DWORD format_flags = depth_stencil_impl->resource.format_desc->Flags; + DWORD format_flags = depth_stencil->resource.format_desc->Flags; - if (use_render_buffer && depth_stencil_impl->current_renderbuffer) + if (use_render_buffer && depth_stencil->current_renderbuffer) { if (format_flags & WINED3DFMT_FLAG_DEPTH) { gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, depth_stencil_impl->current_renderbuffer->id); + GL_RENDERBUFFER, depth_stencil->current_renderbuffer->id); checkGLcall("glFramebufferRenderbuffer()"); } if (format_flags & WINED3DFMT_FLAG_STENCIL) { gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, depth_stencil_impl->current_renderbuffer->id); + GL_RENDERBUFFER, depth_stencil->current_renderbuffer->id); checkGLcall("glFramebufferRenderbuffer()"); } } else { - surface_prepare_texture(depth_stencil_impl, FALSE); + surface_prepare_texture(depth_stencil, gl_info, FALSE); context_apply_attachment_filter_states(depth_stencil); if (format_flags & WINED3DFMT_FLAG_DEPTH) { gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, - depth_stencil_impl->texture_target, depth_stencil_impl->texture_name, - depth_stencil_impl->texture_level); + depth_stencil->texture_target, depth_stencil->texture_name, + depth_stencil->texture_level); checkGLcall("glFramebufferTexture2D()"); } if (format_flags & WINED3DFMT_FLAG_STENCIL) { gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, - depth_stencil_impl->texture_target, depth_stencil_impl->texture_name, - depth_stencil_impl->texture_level); + depth_stencil->texture_target, depth_stencil->texture_name, + depth_stencil->texture_level); checkGLcall("glFramebufferTexture2D()"); } } @@ -249,21 +251,20 @@ void context_attach_depth_stencil_fbo(struct wined3d_context *context, } /* GL locking is done by the caller */ -void context_attach_surface_fbo(const struct wined3d_context *context, - GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) +static void context_attach_surface_fbo(const struct wined3d_context *context, + GLenum fbo_target, DWORD idx, IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; const struct wined3d_gl_info *gl_info = context->gl_info; TRACE("Attach surface %p to %u\n", surface, idx); if (surface) { - surface_prepare_texture(surface_impl, FALSE); + surface_prepare_texture(surface, gl_info, FALSE); context_apply_attachment_filter_states(surface); - gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, surface_impl->texture_target, - surface_impl->texture_name, surface_impl->texture_level); + gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, surface->texture_target, + surface->texture_name, surface->texture_level); checkGLcall("glFramebufferTexture2D()"); } else @@ -274,12 +275,12 @@ void context_attach_surface_fbo(const struct wined3d_context *context, } /* GL locking is done by the caller */ -static void context_check_fbo_status(struct wined3d_context *context) +static void context_check_fbo_status(struct wined3d_context *context, GLenum target) { const struct wined3d_gl_info *gl_info = context->gl_info; GLenum status; - status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER); + status = gl_info->fbo_ops.glCheckFramebufferStatus(target); if (status == GL_FRAMEBUFFER_COMPLETE) { TRACE("FBO complete\n"); @@ -297,7 +298,7 @@ static void context_check_fbo_status(struct wined3d_context *context) /* Dump the FBO attachments */ for (i = 0; i < gl_info->limits.buffers; ++i) { - attachment = (IWineD3DSurfaceImpl *)context->current_fbo->render_targets[i]; + attachment = context->current_fbo->render_targets[i]; if (attachment) { FIXME("\tColor attachment %d: (%p) %s %ux%u\n", @@ -305,7 +306,7 @@ static void context_check_fbo_status(struct wined3d_context *context) attachment->pow2Width, attachment->pow2Height); } } - attachment = (IWineD3DSurfaceImpl *)context->current_fbo->depth_stencil; + attachment = context->current_fbo->depth_stencil; if (attachment) { FIXME("\tDepth attachment: (%p) %s %ux%u\n", @@ -315,16 +316,16 @@ static void context_check_fbo_status(struct wined3d_context *context) } } -static struct fbo_entry *context_create_fbo_entry(struct wined3d_context *context) +static struct fbo_entry *context_create_fbo_entry(struct wined3d_context *context, + IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets)); - memcpy(entry->render_targets, device->render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); - entry->depth_stencil = device->stencilBufferTarget; + memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); + entry->depth_stencil = depth_stencil; entry->attached = FALSE; entry->id = 0; @@ -332,16 +333,17 @@ static struct fbo_entry *context_create_fbo_entry(struct wined3d_context *contex } /* GL locking is done by the caller */ -static void context_reuse_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry) +static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum target, + IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil, + struct fbo_entry *entry) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; - context_bind_fbo(context, GL_FRAMEBUFFER, &entry->id); - context_clean_fbo_attachments(gl_info); + context_bind_fbo(context, target, &entry->id); + context_clean_fbo_attachments(gl_info, target); - memcpy(entry->render_targets, device->render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); - entry->depth_stencil = device->stencilBufferTarget; + memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)); + entry->depth_stencil = depth_stencil; entry->attached = FALSE; } @@ -361,17 +363,17 @@ static void context_destroy_fbo_entry(struct wined3d_context *context, struct fb /* GL locking is done by the caller */ -static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context) +static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, GLenum target, + IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) { if (!memcmp(entry->render_targets, - device->render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)) - && entry->depth_stencil == device->stencilBufferTarget) + render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets)) + && entry->depth_stencil == depth_stencil) { list_remove(&entry->entry); list_add_head(&context->fbo_list, &entry->entry); @@ -381,14 +383,14 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context) if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES) { - entry = context_create_fbo_entry(context); + entry = context_create_fbo_entry(context, render_targets, depth_stencil); list_add_head(&context->fbo_list, &entry->entry); ++context->fbo_entry_count; } else { entry = LIST_ENTRY(list_tail(&context->fbo_list), struct fbo_entry, entry); - context_reuse_fbo_entry(context, entry); + context_reuse_fbo_entry(context, target, render_targets, depth_stencil, entry); list_remove(&entry->entry); list_add_head(&context->fbo_list, &entry->entry); } @@ -397,32 +399,28 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context) } /* GL locking is done by the caller */ -static void context_apply_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry) +static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int i; - context_bind_fbo(context, GL_FRAMEBUFFER, &entry->id); + context_bind_fbo(context, target, &entry->id); if (!entry->attached) { /* Apply render targets */ for (i = 0; i < gl_info->limits.buffers; ++i) { - IWineD3DSurface *render_target = device->render_targets[i]; - context_attach_surface_fbo(context, GL_FRAMEBUFFER, i, render_target); + context_attach_surface_fbo(context, target, i, entry->render_targets[i]); } /* Apply depth targets */ - if (device->stencilBufferTarget) + if (entry->depth_stencil) { - unsigned int w = ((IWineD3DSurfaceImpl *)device->render_targets[0])->pow2Width; - unsigned int h = ((IWineD3DSurfaceImpl *)device->render_targets[0])->pow2Height; - - surface_set_compatible_renderbuffer(device->stencilBufferTarget, w, h); + surface_set_compatible_renderbuffer(entry->depth_stencil, + entry->render_targets[0]->pow2Width, entry->render_targets[0]->pow2Height); } - context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, device->stencilBufferTarget, TRUE); + context_attach_depth_stencil_fbo(context, target, entry->depth_stencil, TRUE); entry->attached = TRUE; } @@ -430,24 +428,17 @@ static void context_apply_fbo_entry(struct wined3d_context *context, struct fbo_ { for (i = 0; i < gl_info->limits.buffers; ++i) { - if (device->render_targets[i]) - context_apply_attachment_filter_states(device->render_targets[i]); + if (entry->render_targets[i]) + context_apply_attachment_filter_states(entry->render_targets[i]); } - if (device->stencilBufferTarget) - context_apply_attachment_filter_states(device->stencilBufferTarget); - } - - for (i = 0; i < gl_info->limits.buffers; ++i) - { - if (device->render_targets[i]) - device->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i; - else - device->draw_buffers[i] = GL_NONE; + if (entry->depth_stencil) + context_apply_attachment_filter_states(entry->depth_stencil); } } /* GL locking is done by the caller */ -static void context_apply_fbo_state(struct wined3d_context *context) +static void context_apply_fbo_state(struct wined3d_context *context, GLenum target, + IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil) { struct fbo_entry *entry, *entry2; @@ -456,16 +447,39 @@ static void context_apply_fbo_state(struct wined3d_context *context) context_destroy_fbo_entry(context, entry); } - if (context->render_offscreen) + if (context->rebind_fbo) { - context->current_fbo = context_find_fbo_entry(context); - context_apply_fbo_entry(context, context->current_fbo); - } else { - context->current_fbo = NULL; context_bind_fbo(context, GL_FRAMEBUFFER, NULL); + context->rebind_fbo = FALSE; + } + + if (render_targets) + { + context->current_fbo = context_find_fbo_entry(context, target, render_targets, depth_stencil); + context_apply_fbo_entry(context, target, context->current_fbo); + } + else + { + context->current_fbo = NULL; + context_bind_fbo(context, target, NULL); } - context_check_fbo_status(context); + context_check_fbo_status(context, target); +} + +/* GL locking is done by the caller */ +void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, + IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil) +{ + if (surface_is_offscreen(render_target)) + { + context->blit_targets[0] = render_target; + context_apply_fbo_state(context, target, context->blit_targets, depth_stencil); + } + else + { + context_apply_fbo_state(context, target, NULL, NULL); + } } /* Context activation is done by the caller. */ @@ -614,13 +628,13 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry, *entry2; - if (context->current_rt == (IWineD3DSurface *)resource) context->current_rt = NULL; + if (context->current_rt == (IWineD3DSurfaceImpl *)resource) context->current_rt = NULL; LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) { UINT j; - if (entry->depth_stencil == (IWineD3DSurface *)resource) + if (entry->depth_stencil == (IWineD3DSurfaceImpl *)resource) { list_remove(&entry->entry); list_add_head(&context->fbo_destroy_list, &entry->entry); @@ -629,7 +643,7 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource for (j = 0; j < gl_info->limits.buffers; ++j) { - if (entry->render_targets[j] == (IWineD3DSurface *)resource) + if (entry->render_targets[j] == (IWineD3DSurfaceImpl *)resource) { list_remove(&entry->entry); list_add_head(&context->fbo_destroy_list, &entry->entry); @@ -647,6 +661,115 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource } } +void context_surface_update(struct wined3d_context *context, IWineD3DSurfaceImpl *surface) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct fbo_entry *entry = context->current_fbo; + unsigned int i; + + if (!entry || context->rebind_fbo) return; + + for (i = 0; i < gl_info->limits.buffers; ++i) + { + if (surface == entry->render_targets[i]) + { + TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i); + context->rebind_fbo = TRUE; + return; + } + } + + if (surface == entry->depth_stencil) + { + TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface); + context->rebind_fbo = TRUE; + } +} + +static BOOL context_set_pixel_format(const struct wined3d_gl_info *gl_info, HDC dc, int format) +{ + int current = GetPixelFormat(dc); + + if (current == format) return TRUE; + + if (!current) + { + if (!SetPixelFormat(dc, format, NULL)) + { + ERR("Failed to set pixel format %d on device context %p, last error %#x.\n", + format, dc, GetLastError()); + return FALSE; + } + return TRUE; + } + + /* By default WGL doesn't allow pixel format adjustments but we need it + * here. For this reason there's a Wine specific wglSetPixelFormat() + * which allows us to set the pixel format multiple times. Only use it + * when really needed. */ + if (gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH]) + { + if (!GL_EXTCALL(wglSetPixelFormatWINE(dc, format, NULL))) + { + ERR("wglSetPixelFormatWINE failed to set pixel format %d on device context %p.\n", + format, dc); + return FALSE; + } + return TRUE; + } + + /* OpenGL doesn't allow pixel format adjustments. Print an error and + * continue using the old format. There's a big chance that the old + * format works although with a performance hit and perhaps rendering + * errors. */ + ERR("Unable to set pixel format %d on device context %p. Already using format %d.\n", + format, dc, current); + return TRUE; +} + +static void context_update_window(struct wined3d_context *context) +{ + TRACE("Updating context %p window from %p to %p.\n", + context, context->win_handle, context->swapchain->win_handle); + + if (context->valid) + { + if (!ReleaseDC(context->win_handle, context->hdc)) + { + ERR("Failed to release device context %p, last error %#x.\n", + context->hdc, GetLastError()); + } + } + else context->valid = 1; + + context->win_handle = context->swapchain->win_handle; + + if (!(context->hdc = GetDC(context->win_handle))) + { + ERR("Failed to get a device context for window %p.\n", context->win_handle); + goto err; + } + + if (!context_set_pixel_format(context->gl_info, context->hdc, context->pixel_format)) + { + ERR("Failed to set pixel format %d on device context %p.\n", + context->pixel_format, context->hdc); + goto err; + } + + if (!pwglMakeCurrent(context->hdc, context->glCtx)) + { + ERR("Failed to make GL context %p current on device context %p, last error %#x.\n", + context->glCtx, context->hdc, GetLastError()); + goto err; + } + + return; + +err: + context->valid = 0; +} + static void context_validate(struct wined3d_context *context) { HWND wnd = WindowFromDC(context->hdc); @@ -657,6 +780,9 @@ static void context_validate(struct wined3d_context *context) context->hdc, wnd, context->win_handle); context->valid = 0; } + + if (context->win_handle != context->swapchain->win_handle) + context_update_window(context); } static void context_destroy_gl_resources(struct wined3d_context *context) @@ -713,11 +839,6 @@ static void context_destroy_gl_resources(struct wined3d_context *context) if (context->valid) { - if (context->src_fbo) - { - TRACE("Destroy src FBO %d\n", context->src_fbo); - context_destroy_fbo(context, &context->src_fbo); - } if (context->dst_fbo) { TRACE("Destroy dst FBO %d\n", context->dst_fbo); @@ -772,15 +893,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ERR("Failed to disable GL context.\n"); } - if (context->pbuffer) - { - GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc)); - GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer)); - } - else - { - ReleaseDC(context->win_handle, context->hdc); - } + ReleaseDC(context->win_handle, context->hdc); if (!pwglDeleteContext(context->glCtx)) { @@ -928,68 +1041,10 @@ static void Context_MarkStateDirty(struct wined3d_context *context, DWORD state, context->isStateDirty[idx] |= (1 << shift); } -/***************************************************************************** - * AddContextToArray - * - * Adds a context to the context array. Helper function for context_create(). - * - * This method is not called in performance-critical code paths, only when a - * new render target or swapchain is created. Thus performance is not an issue - * here. - * - * Params: - * This: Device to add the context for - * hdc: device context - * glCtx: WGL context to add - * pbuffer: optional pbuffer used with this context - * - *****************************************************************************/ -static struct wined3d_context *AddContextToArray(IWineD3DDeviceImpl *This, - HWND win_handle, HDC hdc, HGLRC glCtx, HPBUFFERARB pbuffer) -{ - struct wined3d_context **oldArray = This->contexts; - DWORD state; - - This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * (This->numContexts + 1)); - if(This->contexts == NULL) { - ERR("Unable to grow the context array\n"); - This->contexts = oldArray; - return NULL; - } - if(oldArray) { - memcpy(This->contexts, oldArray, sizeof(*This->contexts) * This->numContexts); - } - - This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**This->contexts)); - if(This->contexts[This->numContexts] == NULL) { - ERR("Unable to allocate a new context\n"); - HeapFree(GetProcessHeap(), 0, This->contexts); - This->contexts = oldArray; - return NULL; - } - - This->contexts[This->numContexts]->hdc = hdc; - This->contexts[This->numContexts]->glCtx = glCtx; - This->contexts[This->numContexts]->pbuffer = pbuffer; - This->contexts[This->numContexts]->win_handle = win_handle; - HeapFree(GetProcessHeap(), 0, oldArray); - - /* Mark all states dirty to force a proper initialization of the states on the first use of the context - */ - for(state = 0; state <= STATE_HIGHEST; state++) { - if (This->StateTable[state].representative) - Context_MarkStateDirty(This->contexts[This->numContexts], state, This->StateTable); - } - - This->numContexts++; - TRACE("Created context %p\n", This->contexts[This->numContexts - 1]); - return This->contexts[This->numContexts - 1]; -} - /* This function takes care of WineD3D pixel format selection. */ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, - const struct GlPixelFormatDesc *color_format_desc, const struct GlPixelFormatDesc *ds_format_desc, - BOOL auxBuffers, int numSamples, BOOL pbuffer, BOOL findCompatible) + const struct wined3d_format_desc *color_format_desc, const struct wined3d_format_desc *ds_format_desc, + BOOL auxBuffers, int numSamples, BOOL findCompatible) { int iPixelFormat=0; unsigned int matchtry; @@ -1019,9 +1074,9 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, int i = 0; int nCfgs = This->adapter->nCfgs; - TRACE("ColorFormat=%s, DepthStencilFormat=%s, auxBuffers=%d, numSamples=%d, pbuffer=%d, findCompatible=%d\n", + TRACE("ColorFormat=%s, DepthStencilFormat=%s, auxBuffers=%d, numSamples=%d, findCompatible=%d\n", debug_d3dformat(color_format_desc->format), debug_d3dformat(ds_format_desc->format), - auxBuffers, numSamples, pbuffer, findCompatible); + auxBuffers, numSamples, findCompatible); if (!getColorBits(color_format_desc, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits)) { @@ -1030,23 +1085,6 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, return 0; } - /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate. - * You are able to add a depth + stencil surface at a later stage when you need it. - * In order to support this properly in WineD3D we need the ability to recreate the opengl context and - * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new - * context, need torecreate shaders, textures and other resources. - * - * The context manager already takes care of the state problem and for the other tasks code from Reset - * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now. - * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the - * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this - * issue needs to be fixed. */ - if (ds_format_desc->format != WINED3DFMT_D24_UNORM_S8_UINT) - { - FIXME("Add OpenGL context recreation support to SetDepthStencilSurface\n"); - ds_format_desc = getFormatDescEntry(WINED3DFMT_D24_UNORM_S8_UINT, &This->adapter->gl_info); - } - getDepthStencilBits(ds_format_desc, &depthBits, &stencilBits); for(matchtry = 0; matchtry < (sizeof(matches) / sizeof(matches[0])) && !iPixelFormat; matchtry++) { @@ -1059,18 +1097,14 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, if(cfg->iPixelType != WGL_TYPE_RGBA_ARB) continue; - /* In window mode (!pbuffer) we need a window drawable format and double buffering. */ - if(!pbuffer && !(cfg->windowDrawable && cfg->doubleBuffer)) + /* In window mode we need a window drawable format and double buffering. */ + if(!(cfg->windowDrawable && cfg->doubleBuffer)) continue; /* We like to have aux buffers in backbuffer mode */ if(auxBuffers && !cfg->auxBuffers && matches[matchtry].require_aux) continue; - /* In pbuffer-mode we need a pbuffer-capable format but we don't want double buffering */ - if(pbuffer && (!cfg->pbufferDrawable || cfg->doubleBuffer)) - continue; - if(matches[matchtry].exact_color) { if(cfg->redSize != redBits) continue; @@ -1167,227 +1201,174 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, /***************************************************************************** * context_create * - * Creates a new context for a window, or a pbuffer context. + * Creates a new context. * * * Params: * This: Device to activate the context for * target: Surface this context will render to * win_handle: handle to the window which we are drawing to - * create_pbuffer: tells whether to create a pbuffer or not * pPresentParameters: contains the pixelformats to use for onscreen rendering * *****************************************************************************/ -struct wined3d_context *context_create(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, - HWND win_handle, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms) +struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target, + const struct wined3d_format_desc *ds_format_desc) { - const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; - struct wined3d_context *ret = NULL; - HPBUFFERARB pbuffer = NULL; + IWineD3DDeviceImpl *device = swapchain->device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct wined3d_format_desc *color_format_desc; + struct wined3d_context *ret; + PIXELFORMATDESCRIPTOR pfd; + BOOL auxBuffers = FALSE; + int numSamples = 0; + int pixel_format; unsigned int s; + DWORD state; HGLRC ctx; HDC hdc; - TRACE("(%p): Creating a %s context for render target %p\n", This, create_pbuffer ? "offscreen" : "onscreen", target); + TRACE("swapchain %p, target %p, window %p.\n", swapchain, target, swapchain->win_handle); - if(create_pbuffer) { - HDC hdc_parent = GetDC(win_handle); - int iPixelFormat = 0; - - IWineD3DSurface *StencilSurface = This->stencilBufferTarget; - const struct GlPixelFormatDesc *ds_format_desc = StencilSurface - ? ((IWineD3DSurfaceImpl *)StencilSurface)->resource.format_desc - : getFormatDescEntry(WINED3DFMT_UNKNOWN, &This->adapter->gl_info); - - /* Try to find a pixel format with pbuffer support. */ - iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format_desc, - ds_format_desc, FALSE /* auxBuffers */, 0 /* numSamples */, TRUE /* PBUFFER */, - FALSE /* findCompatible */); - if(!iPixelFormat) { - TRACE("Trying to locate a compatible pixel format because an exact match failed.\n"); - - /* For some reason we weren't able to find a format, try to find something instead of crashing. - * A reason for failure could have been wglChoosePixelFormatARB strictness. */ - iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format_desc, - ds_format_desc, FALSE /* auxBuffer */, 0 /* numSamples */, TRUE /* PBUFFER */, - TRUE /* findCompatible */); - } + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); + if (!ret) + { + ERR("Failed to allocate context memory.\n"); + return NULL; + } - /* This shouldn't happen as ChoosePixelFormat always returns something */ - if(!iPixelFormat) { - ERR("Unable to locate a pixel format for a pbuffer\n"); - ReleaseDC(win_handle, hdc_parent); - goto out; - } + if (!(hdc = GetDC(swapchain->win_handle))) + { + ERR("Failed to retrieve a device context.\n"); + goto out; + } - TRACE("Creating a pBuffer drawable for the new context\n"); - pbuffer = GL_EXTCALL(wglCreatePbufferARB(hdc_parent, iPixelFormat, target->currentDesc.Width, target->currentDesc.Height, 0)); - if(!pbuffer) { - ERR("Cannot create a pbuffer\n"); - ReleaseDC(win_handle, hdc_parent); - goto out; - } + color_format_desc = target->resource.format_desc; - /* In WGL a pbuffer is 'wrapped' inside a HDC to 'fool' wglMakeCurrent */ - hdc = GL_EXTCALL(wglGetPbufferDCARB(pbuffer)); - if(!hdc) { - ERR("Cannot get a HDC for pbuffer (%p)\n", pbuffer); - GL_EXTCALL(wglDestroyPbufferARB(pbuffer)); - ReleaseDC(win_handle, hdc_parent); - goto out; - } - ReleaseDC(win_handle, hdc_parent); - } else { - PIXELFORMATDESCRIPTOR pfd; - int iPixelFormat; - int res; - const struct GlPixelFormatDesc *color_format_desc = target->resource.format_desc; - const struct GlPixelFormatDesc *ds_format_desc = getFormatDescEntry(WINED3DFMT_UNKNOWN, - &This->adapter->gl_info); - BOOL auxBuffers = FALSE; - int numSamples = 0; - - hdc = GetDC(win_handle); - if(hdc == NULL) { - ERR("Cannot retrieve a device context!\n"); - goto out; - } - - /* In case of ORM_BACKBUFFER, make sure to request an alpha component for X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */ - if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) { - auxBuffers = TRUE; - - if (color_format_desc->format == WINED3DFMT_B4G4R4X4_UNORM) - color_format_desc = getFormatDescEntry(WINED3DFMT_B4G4R4A4_UNORM, &This->adapter->gl_info); - else if (color_format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) - color_format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, &This->adapter->gl_info); - } - - /* DirectDraw supports 8bit paletted render targets and these are used by old games like Starcraft and C&C. - * Most modern hardware doesn't support 8bit natively so we perform some form of 8bit -> 32bit conversion. - * The conversion (ab)uses the alpha component for storing the palette index. For this reason we require - * a format with 8bit alpha, so request A8R8G8B8. */ - if (color_format_desc->format == WINED3DFMT_P8_UINT) - color_format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, &This->adapter->gl_info); - - /* Retrieve the depth stencil format from the present parameters. - * The choice of the proper format can give a nice performance boost - * in case of GPU limited programs. */ - if(pPresentParms->EnableAutoDepthStencil) { - TRACE("pPresentParms->EnableAutoDepthStencil=enabled; using AutoDepthStencilFormat=%s\n", debug_d3dformat(pPresentParms->AutoDepthStencilFormat)); - ds_format_desc = getFormatDescEntry(pPresentParms->AutoDepthStencilFormat, &This->adapter->gl_info); - } - - /* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD */ - if(pPresentParms->MultiSampleType && (pPresentParms->SwapEffect == WINED3DSWAPEFFECT_DISCARD)) { - if (!gl_info->supported[ARB_MULTISAMPLE]) - ERR("The program is requesting multisampling without support!\n"); - else - { - TRACE("Requesting multisample type %#x.\n", pPresentParms->MultiSampleType); - numSamples = pPresentParms->MultiSampleType; - } - } + /* In case of ORM_BACKBUFFER, make sure to request an alpha component for + * X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */ + if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) + { + auxBuffers = TRUE; - /* Try to find a pixel format which matches our requirements */ - iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, color_format_desc, ds_format_desc, - auxBuffers, numSamples, FALSE /* PBUFFER */, FALSE /* findCompatible */); + if (color_format_desc->format == WINED3DFMT_B4G4R4X4_UNORM) + color_format_desc = getFormatDescEntry(WINED3DFMT_B4G4R4A4_UNORM, gl_info); + else if (color_format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) + color_format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info); + } - /* Try to locate a compatible format if we weren't able to find anything */ - if(!iPixelFormat) { - TRACE("Trying to locate a compatible pixel format because an exact match failed.\n"); - iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, color_format_desc, ds_format_desc, - auxBuffers, 0 /* numSamples */, FALSE /* PBUFFER */, TRUE /* findCompatible */ ); - } + /* DirectDraw supports 8bit paletted render targets and these are used by + * old games like Starcraft and C&C. Most modern hardware doesn't support + * 8bit natively so we perform some form of 8bit -> 32bit conversion. The + * conversion (ab)uses the alpha component for storing the palette index. + * For this reason we require a format with 8bit alpha, so request + * A8R8G8B8. */ + if (color_format_desc->format == WINED3DFMT_P8_UINT) + color_format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info); - /* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */ - if(!iPixelFormat) { - ERR("Can't find a suitable iPixelFormat\n"); - return NULL; + /* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD. */ + if (swapchain->presentParms.MultiSampleType && (swapchain->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD)) + { + if (!gl_info->supported[ARB_MULTISAMPLE]) + WARN("The application is requesting multisampling without support.\n"); + else + { + TRACE("Requesting multisample type %#x.\n", swapchain->presentParms.MultiSampleType); + numSamples = swapchain->presentParms.MultiSampleType; } + } - DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd); - res = SetPixelFormat(hdc, iPixelFormat, NULL); - if(!res) { - int oldPixelFormat = GetPixelFormat(hdc); + /* Try to find a pixel format which matches our requirements. */ + pixel_format = WineD3D_ChoosePixelFormat(device, hdc, color_format_desc, ds_format_desc, + auxBuffers, numSamples, FALSE /* findCompatible */); - /* By default WGL doesn't allow pixel format adjustments but we need it here. - * For this reason there is a WINE-specific wglSetPixelFormat which allows you to - * set the pixel format multiple times. Only use it when it is really needed. */ + /* Try to locate a compatible format if we weren't able to find anything. */ + if (!pixel_format) + { + TRACE("Trying to locate a compatible pixel format because an exact match failed.\n"); + pixel_format = WineD3D_ChoosePixelFormat(device, hdc, color_format_desc, ds_format_desc, + auxBuffers, 0 /* numSamples */, TRUE /* findCompatible */); + } - if(oldPixelFormat == iPixelFormat) { - /* We don't have to do anything as the formats are the same :) */ - } - else if (oldPixelFormat && gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH]) - { - res = GL_EXTCALL(wglSetPixelFormatWINE(hdc, iPixelFormat, NULL)); + /* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */ + if (!pixel_format) + { + ERR("Can't find a suitable pixel format.\n"); + goto out; + } - if(!res) { - ERR("wglSetPixelFormatWINE failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); - return NULL; - } - } else if(oldPixelFormat) { - /* OpenGL doesn't allow pixel format adjustments. Print an error and continue using the old format. - * There's a big chance that the old format works although with a performance hit and perhaps rendering errors. */ - ERR("HDC=%p is already set to iPixelFormat=%d and OpenGL doesn't allow changes!\n", hdc, oldPixelFormat); - } else { - ERR("SetPixelFormat failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); - return NULL; - } - } + DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); + if (!context_set_pixel_format(gl_info, hdc, pixel_format)) + { + ERR("Failed to set pixel format %d on device context %p.\n", pixel_format, hdc); + goto out; } ctx = pwglCreateContext(hdc); - if (This->numContexts) + if (device->numContexts) { - if (!pwglShareLists(This->contexts[0]->glCtx, ctx)) + if (!pwglShareLists(device->contexts[0]->glCtx, ctx)) { DWORD err = GetLastError(); ERR("wglShareLists(%p, %p) failed, last error %#x.\n", - This->contexts[0]->glCtx, ctx, err); + device->contexts[0]->glCtx, ctx, err); } } if(!ctx) { ERR("Failed to create a WGL context\n"); - if(create_pbuffer) { - GL_EXTCALL(wglReleasePbufferDCARB(pbuffer, hdc)); - GL_EXTCALL(wglDestroyPbufferARB(pbuffer)); - } goto out; } - ret = AddContextToArray(This, win_handle, hdc, ctx, pbuffer); - if(!ret) { + + if (!device_context_add(device, ret)) + { ERR("Failed to add the newly created context to the context list\n"); if (!pwglDeleteContext(ctx)) { DWORD err = GetLastError(); ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, err); } - if(create_pbuffer) { - GL_EXTCALL(wglReleasePbufferDCARB(pbuffer, hdc)); - GL_EXTCALL(wglDestroyPbufferARB(pbuffer)); - } goto out; } - ret->valid = 1; - ret->gl_info = &This->adapter->gl_info; - ret->surface = (IWineD3DSurface *) target; - ret->current_rt = (IWineD3DSurface *)target; - ret->render_offscreen = surface_is_offscreen((IWineD3DSurface *) target); - ret->draw_buffer_dirty = TRUE; + + ret->gl_info = gl_info; + + /* Mark all states dirty to force a proper initialization of the states + * on the first use of the context. */ + for (state = 0; state <= STATE_HIGHEST; ++state) + { + if (device->StateTable[state].representative) + Context_MarkStateDirty(ret, state, device->StateTable); + } + + ret->swapchain = swapchain; + ret->current_rt = target; ret->tid = GetCurrentThreadId(); - if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) { + + ret->render_offscreen = surface_is_offscreen(target); + ret->draw_buffer_dirty = TRUE; + ret->valid = 1; + + ret->glCtx = ctx; + ret->win_handle = swapchain->win_handle; + ret->hdc = hdc; + ret->pixel_format = pixel_format; + + if (device->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *)device)) + { /* Create the dirty constants array and initialize them to dirty */ ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, - sizeof(*ret->vshader_const_dirty) * This->d3d_vshader_constantF); + sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF); ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, - sizeof(*ret->pshader_const_dirty) * This->d3d_pshader_constantF); + sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF); memset(ret->vshader_const_dirty, 1, - sizeof(*ret->vshader_const_dirty) * This->d3d_vshader_constantF); + sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF); memset(ret->pshader_const_dirty, 1, - sizeof(*ret->pshader_const_dirty) * This->d3d_pshader_constantF); + sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF); } + ret->blit_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + gl_info->limits.buffers * sizeof(*ret->blit_targets)); + if (!ret->blit_targets) goto out; + ret->free_occlusion_query_size = 4; ret->free_occlusion_queries = HeapAlloc(GetProcessHeap(), 0, ret->free_occlusion_query_size * sizeof(*ret->free_occlusion_queries)); @@ -1440,10 +1421,10 @@ struct wined3d_context *context_create(IWineD3DDeviceImpl *This, IWineD3DSurface glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);"); - glPixelStorei(GL_PACK_ALIGNMENT, This->surface_alignment); - checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, This->surface_alignment);"); - glPixelStorei(GL_UNPACK_ALIGNMENT, This->surface_alignment); - checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, This->surface_alignment);"); + glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment); + checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);"); + glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment); + checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);"); if (gl_info->supported[APPLE_CLIENT_STORAGE]) { @@ -1512,83 +1493,22 @@ struct wined3d_context *context_create(IWineD3DDeviceImpl *This, IWineD3DSurface LEAVE_GL(); - This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); + device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE); + + TRACE("Created context %p.\n", ret); return ret; out: - if (ret) - { - HeapFree(GetProcessHeap(), 0, ret->free_event_queries); - HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); - HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty); - HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty); - HeapFree(GetProcessHeap(), 0, ret); - } + HeapFree(GetProcessHeap(), 0, ret->free_event_queries); + HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, ret->blit_targets); + HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty); + HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty); + HeapFree(GetProcessHeap(), 0, ret); return NULL; } -/***************************************************************************** - * RemoveContextFromArray - * - * Removes a context from the context manager. The opengl context is not - * destroyed or unset. context is not a valid pointer after that call. - * - * Similar to the former call this isn't a performance critical function. A - * helper function for context_destroy(). - * - * Params: - * This: Device to activate the context for - * context: Context to remove - * - *****************************************************************************/ -static void RemoveContextFromArray(IWineD3DDeviceImpl *This, struct wined3d_context *context) -{ - struct wined3d_context **new_array; - BOOL found = FALSE; - UINT i; - - TRACE("Removing ctx %p\n", context); - - for (i = 0; i < This->numContexts; ++i) - { - if (This->contexts[i] == context) - { - found = TRUE; - break; - } - } - - if (!found) - { - ERR("Context %p doesn't exist in context array\n", context); - return; - } - - while (i < This->numContexts - 1) - { - This->contexts[i] = This->contexts[i + 1]; - ++i; - } - - --This->numContexts; - if (!This->numContexts) - { - HeapFree(GetProcessHeap(), 0, This->contexts); - This->contexts = NULL; - return; - } - - new_array = HeapReAlloc(GetProcessHeap(), 0, This->contexts, This->numContexts * sizeof(*This->contexts)); - if (!new_array) - { - ERR("Failed to shrink context array. Oh well.\n"); - return; - } - - This->contexts = new_array; -} - /***************************************************************************** * context_destroy * @@ -1617,9 +1537,10 @@ void context_destroy(IWineD3DDeviceImpl *This, struct wined3d_context *context) destroy = FALSE; } + HeapFree(GetProcessHeap(), 0, context->blit_targets); HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty); HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty); - RemoveContextFromArray(This, context); + device_context_remove(This, context); if (destroy) HeapFree(GetProcessHeap(), 0, context); } @@ -1657,8 +1578,8 @@ static void SetupForBlit(IWineD3DDeviceImpl *This, struct wined3d_context *conte int i; const struct StateEntry *StateTable = This->StateTable; const struct wined3d_gl_info *gl_info = context->gl_info; - UINT width = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Width; - UINT height = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height; + UINT width = context->current_rt->currentDesc.Width; + UINT height = context->current_rt->currentDesc.Height; DWORD sampler; TRACE("Setting up context %p for blitting\n", context); @@ -1811,6 +1732,9 @@ static void SetupForBlit(IWineD3DDeviceImpl *This, struct wined3d_context *conte glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); checkGLcall("glColorMask"); Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE), StateTable); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), StateTable); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), StateTable); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), StateTable); if (gl_info->supported[EXT_SECONDARY_COLOR]) { glDisable(GL_COLOR_SUM_EXT); @@ -1882,14 +1806,12 @@ static struct wined3d_context *findThreadContextForSwapChain(IWineD3DSwapChain * * Returns: The needed context * *****************************************************************************/ -static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target) +static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target) { IWineD3DSwapChain *swapchain = NULL; struct wined3d_context *current_context = context_get_current(); - const struct StateEntry *StateTable = This->StateTable; DWORD tid = GetCurrentThreadId(); struct wined3d_context *context; - BOOL old_render_offscreen; if (current_context && current_context->destroyed) current_context = NULL; @@ -1897,15 +1819,15 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur { if (current_context && current_context->current_rt - && ((IWineD3DSurfaceImpl *)current_context->surface)->resource.device == This) + && current_context->swapchain->device == This) { target = current_context->current_rt; } else { IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)This->swapchains[0]; - if (swapchain->backBuffer) target = swapchain->backBuffer[0]; - else target = swapchain->frontBuffer; + if (swapchain->back_buffers) target = swapchain->back_buffers[0]; + else target = swapchain->front_buffer; } } @@ -1915,165 +1837,36 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur return current_context; } - if (SUCCEEDED(IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain))) { + if (target->Flags & SFLAG_SWAPCHAIN) + { TRACE("Rendering onscreen\n"); + swapchain = (IWineD3DSwapChain *)target->container; context = findThreadContextForSwapChain(swapchain, tid); - - old_render_offscreen = context->render_offscreen; - context->render_offscreen = surface_is_offscreen(target); - /* The context != This->activeContext will catch a NOP context change. This can occur - * if we are switching back to swapchain rendering in case of FBO or Back Buffer offscreen - * rendering. No context change is needed in that case - */ - - if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) { - if(This->pbufferContext && tid == This->pbufferContext->tid) { - This->pbufferContext->tid = 0; - } - } - IWineD3DSwapChain_Release(swapchain); } else { TRACE("Rendering offscreen\n"); -retry: - if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) + /* Stay with the currently active context. */ + if (current_context && current_context->swapchain->device == This) { - IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *)target; - if (!This->pbufferContext - || This->pbufferWidth < targetimpl->currentDesc.Width - || This->pbufferHeight < targetimpl->currentDesc.Height) - { - if (This->pbufferContext) context_destroy(This, This->pbufferContext); - - /* The display is irrelevant here, the window is 0. But - * context_create() needs a valid X connection. Create the context - * on the same server as the primary swapchain. The primary - * swapchain is exists at this point. */ - This->pbufferContext = context_create(This, targetimpl, - ((IWineD3DSwapChainImpl *)This->swapchains[0])->context[0]->win_handle, - TRUE /* pbuffer */, &((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms); - This->pbufferWidth = targetimpl->currentDesc.Width; - This->pbufferHeight = targetimpl->currentDesc.Height; - if (This->pbufferContext) context_release(This->pbufferContext); - } - - if (This->pbufferContext) - { - if (This->pbufferContext->tid && This->pbufferContext->tid != tid) - { - FIXME("The PBuffer context is only supported for one thread for now!\n"); - } - This->pbufferContext->tid = tid; - context = This->pbufferContext; - } - else - { - ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering.\n"); - wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; - goto retry; - } + context = current_context; } else { - /* Stay with the currently active context. */ - if (current_context - && ((IWineD3DSurfaceImpl *)current_context->surface)->resource.device == This) - { - context = current_context; - } - else - { - /* This may happen if the app jumps straight into offscreen rendering - * Start using the context of the primary swapchain. tid == 0 is no problem - * for findThreadContextForSwapChain. - * - * Can also happen on thread switches - in that case findThreadContextForSwapChain - * is perfect to call. */ - context = findThreadContextForSwapChain(This->swapchains[0], tid); - } + /* This may happen if the app jumps straight into offscreen rendering + * Start using the context of the primary swapchain. tid == 0 is no problem + * for findThreadContextForSwapChain. + * + * Can also happen on thread switches - in that case findThreadContextForSwapChain + * is perfect to call. */ + context = findThreadContextForSwapChain(This->swapchains[0], tid); } - - old_render_offscreen = context->render_offscreen; - context->render_offscreen = TRUE; } context_validate(context); - if (context->render_offscreen != old_render_offscreen) - { - Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable); - Context_MarkStateDirty(context, STATE_VDECL, StateTable); - Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable); - Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable); - Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable); - } - - /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers - * the alpha blend state changes with different render target formats. */ - if (!context->current_rt) - { - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); - } - else - { - const struct GlPixelFormatDesc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc; - const struct GlPixelFormatDesc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc; - - if (old->format != new->format) - { - /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */ - if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask) - || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) - { - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); - } - } - - /* When switching away from an offscreen render target, and we're not - * using FBOs, we have to read the drawable into the texture. This is - * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There - * are some things that need care though. PreLoad needs a GL context, - * and FindContext is called before the context is activated. It also - * has to be called with the old rendertarget active, otherwise a - * wrong drawable is read. */ - if (wined3d_settings.offscreen_rendering_mode != ORM_FBO - && old_render_offscreen && context->current_rt != target) - { - BOOL oldInDraw = This->isInDraw; - - /* surface_internal_preload() requires a context to load the - * texture, so it will call context_acquire(). Set isInDraw to true - * to signal surface_internal_preload() that it has a context. */ - - /* FIXME: This is just broken. There's no guarantee whatsoever - * that the currently active context, if any, is appropriate for - * reading back the render target. We should probably call - * context_set_current(context) here and then rely on - * context_acquire() doing the right thing. */ - This->isInDraw = TRUE; - - /* Read the back buffer of the old drawable into the destination texture. */ - if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb) - { - surface_internal_preload(context->current_rt, SRGB_BOTH); - } - else - { - surface_internal_preload(context->current_rt, SRGB_RGB); - } - - IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE); - - This->isInDraw = oldInDraw; - } - } - - context->draw_buffer_dirty = TRUE; - context->current_rt = target; - return context; } @@ -2081,10 +1874,10 @@ retry: static void context_apply_draw_buffer(struct wined3d_context *context, BOOL blit) { const struct wined3d_gl_info *gl_info = context->gl_info; - IWineD3DSurface *rt = context->current_rt; + IWineD3DSurfaceImpl *rt = context->current_rt; IWineD3DDeviceImpl *device; - device = ((IWineD3DSurfaceImpl *)rt)->resource.device; + device = rt->resource.device; if (!surface_is_offscreen(rt)) { ENTER_GL(); @@ -2099,6 +1892,16 @@ static void context_apply_draw_buffer(struct wined3d_context *context, BOOL blit { if (!blit) { + unsigned int i; + + for (i = 0; i < gl_info->limits.buffers; ++i) + { + if (device->render_targets[i]) + device->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i; + else + device->draw_buffers[i] = GL_NONE; + } + if (gl_info->supported[ARB_DRAW_BUFFERS]) { GL_EXTCALL(glDrawBuffersARB(gl_info->limits.buffers, device->draw_buffers)); @@ -2131,116 +1934,268 @@ void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) context->draw_buffer_dirty = TRUE; } +static inline void context_set_render_offscreen(struct wined3d_context *context, const struct StateEntry *StateTable, + BOOL offscreen) +{ + if (context->render_offscreen == offscreen) return; + + Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable); + Context_MarkStateDirty(context, STATE_VDECL, StateTable); + Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable); + Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable); + Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable); + context->render_offscreen = offscreen; +} + +static BOOL match_depth_stencil_format(const struct wined3d_format_desc *existing, + const struct wined3d_format_desc *required) +{ + short existing_depth, existing_stencil, required_depth, required_stencil; + + if(existing == required) return TRUE; + if((existing->Flags & WINED3DFMT_FLAG_FLOAT) != (required->Flags & WINED3DFMT_FLAG_FLOAT)) return FALSE; + + getDepthStencilBits(existing, &existing_depth, &existing_stencil); + getDepthStencilBits(required, &required_depth, &required_stencil); + + if(existing_depth < required_depth) return FALSE; + /* If stencil bits are used the exact amount is required - otherwise wrapping + * won't work correctly */ + if(required_stencil && required_stencil != existing_stencil) return FALSE; + return TRUE; +} +/* The caller provides a context */ +static void context_validate_onscreen_formats(IWineD3DDeviceImpl *device, + struct wined3d_context *context, IWineD3DSurfaceImpl *depth_stencil) +{ + /* Onscreen surfaces are always in a swapchain */ + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)context->current_rt->container; + + if (context->render_offscreen || !depth_stencil) return; + if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format_desc)) return; + + /* TODO: If the requested format would satisfy the needs of the existing one(reverse match), + * or no onscreen depth buffer was created, the OpenGL drawable could be changed to the new + * format. */ + WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n"); + + /* The currently active context is the necessary context to access the swapchain's onscreen buffers */ + IWineD3DSurface_LoadLocation((IWineD3DSurface *)context->current_rt, SFLAG_INTEXTURE, NULL); + swapchain->render_to_fbo = TRUE; + context_set_render_offscreen(context, device->StateTable, TRUE); +} + +/* Context activation is done by the caller. */ +void context_apply_blit_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) +{ + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + context_validate_onscreen_formats(device, context, NULL); + + if (context->render_offscreen) + { + FIXME("Applying blit state for an offscreen target with ORM_FBO. This should be avoided.\n"); + surface_internal_preload(context->current_rt, SRGB_RGB); + + ENTER_GL(); + context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, context->current_rt, NULL); + LEAVE_GL(); + } + else + { + ENTER_GL(); + context_bind_fbo(context, GL_FRAMEBUFFER, NULL); + LEAVE_GL(); + } + + context->draw_buffer_dirty = TRUE; + } + + if (context->draw_buffer_dirty) + { + context_apply_draw_buffer(context, TRUE); + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + context->draw_buffer_dirty = FALSE; + } + + SetupForBlit(device, context); +} + /* Context activation is done by the caller. */ -static void context_apply_state(struct wined3d_context *context, IWineD3DDeviceImpl *device, enum ContextUsage usage) +void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device, + IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil) { const struct StateEntry *state_table = device->StateTable; - unsigned int i; + GLenum buffer; - switch (usage) { - case CTXUSAGE_CLEAR: - case CTXUSAGE_DRAWPRIM: - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - ENTER_GL(); - context_apply_fbo_state(context); - LEAVE_GL(); - } - if (context->draw_buffer_dirty) { - context_apply_draw_buffer(context, FALSE); - context->draw_buffer_dirty = FALSE; - } - break; + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + context_validate_onscreen_formats(device, context, depth_stencil); - case CTXUSAGE_BLIT: - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - if (context->render_offscreen) - { - FIXME("Activating for CTXUSAGE_BLIT for an offscreen target with ORM_FBO. This should be avoided.\n"); - surface_internal_preload(context->current_rt, SRGB_RGB); - - ENTER_GL(); - context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo); - context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, context->current_rt); - context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, NULL, FALSE); - LEAVE_GL(); - } else { - ENTER_GL(); - context_bind_fbo(context, GL_FRAMEBUFFER, NULL); - LEAVE_GL(); - } - context->draw_buffer_dirty = TRUE; - } - if (context->draw_buffer_dirty) { - context_apply_draw_buffer(context, TRUE); - if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) { - context->draw_buffer_dirty = FALSE; - } - } - break; + ENTER_GL(); + context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, render_target, depth_stencil); + LEAVE_GL(); + } - default: - break; + if (!surface_is_offscreen(render_target)) + buffer = surface_get_gl_buffer(render_target); + else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + buffer = GL_COLOR_ATTACHMENT0; + else + buffer = device->offscreenBuffer; + + ENTER_GL(); + context_set_draw_buffer(context, buffer); + LEAVE_GL(); + + if (context->last_was_blit) + { + device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE); } - switch(usage) { - case CTXUSAGE_RESOURCELOAD: - /* This does not require any special states to be set up */ - break; + /* Blending and clearing should be orthogonal, but tests on the nvidia + * driver show that disabling blending when clearing improves the clearing + * performance incredibly. */ + ENTER_GL(); + glDisable(GL_BLEND); + glEnable(GL_SCISSOR_TEST); + checkGLcall("glEnable GL_SCISSOR_TEST"); + LEAVE_GL(); - case CTXUSAGE_CLEAR: - if(context->last_was_blit) { - device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE); - } + context->last_was_blit = FALSE; + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_table); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_table); + Context_MarkStateDirty(context, STATE_SCISSORRECT, state_table); +} - /* Blending and clearing should be orthogonal, but tests on the nvidia driver show that disabling - * blending when clearing improves the clearing performance incredibly. - */ +/* Context activation is done by the caller. */ +void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) +{ + const struct StateEntry *state_table = device->StateTable; + unsigned int i; + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + context_validate_onscreen_formats(device, context, device->depth_stencil); + + if (!context->render_offscreen) + { ENTER_GL(); - glDisable(GL_BLEND); + context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL); LEAVE_GL(); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_table); - + } + else + { ENTER_GL(); - glEnable(GL_SCISSOR_TEST); - checkGLcall("glEnable GL_SCISSOR_TEST"); + context_apply_fbo_state(context, GL_FRAMEBUFFER, device->render_targets, device->depth_stencil); LEAVE_GL(); - context->last_was_blit = FALSE; - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_table); - Context_MarkStateDirty(context, STATE_SCISSORRECT, state_table); - break; + } + } + + if (context->draw_buffer_dirty) + { + context_apply_draw_buffer(context, FALSE); + context->draw_buffer_dirty = FALSE; + } + + if (context->last_was_blit) + { + device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE); + } + + IWineD3DDeviceImpl_FindTexUnitMap(device); + device_preload_textures(device); + if (isStateDirty(context, STATE_VDECL)) + device_update_stream_info(device, context->gl_info); + + ENTER_GL(); + for (i = 0; i < context->numDirtyEntries; ++i) + { + DWORD rep = context->dirtyArray[i]; + DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT); + BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1); + context->isStateDirty[idx] &= ~(1 << shift); + state_table[rep].apply(rep, device->stateBlock, context); + } + LEAVE_GL(); + context->numDirtyEntries = 0; /* This makes the whole list clean */ + context->last_was_blit = FALSE; +} + +static void context_setup_target(IWineD3DDeviceImpl *device, + struct wined3d_context *context, IWineD3DSurfaceImpl *target) +{ + BOOL old_render_offscreen = context->render_offscreen, render_offscreen; + const struct StateEntry *StateTable = device->StateTable; + + if (!target) return; + else if (context->current_rt == target) return; + render_offscreen = surface_is_offscreen(target); + + context_set_render_offscreen(context, StateTable, render_offscreen); + + /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers + * the alpha blend state changes with different render target formats. */ + if (!context->current_rt) + { + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + } + else + { + const struct wined3d_format_desc *old = context->current_rt->resource.format_desc; + const struct wined3d_format_desc *new = target->resource.format_desc; - case CTXUSAGE_DRAWPRIM: - /* This needs all dirty states applied */ - if(context->last_was_blit) { - device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE); + if (old->format != new->format) + { + /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */ + if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask) + || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) + { + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); } + } - IWineD3DDeviceImpl_FindTexUnitMap(device); - device_preload_textures(device); - if (isStateDirty(context, STATE_VDECL)) - device_update_stream_info(device, context->gl_info); + /* When switching away from an offscreen render target, and we're not + * using FBOs, we have to read the drawable into the texture. This is + * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There + * are some things that need care though. PreLoad needs a GL context, + * and FindContext is called before the context is activated. It also + * has to be called with the old rendertarget active, otherwise a + * wrong drawable is read. */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO + && old_render_offscreen && context->current_rt != target) + { + BOOL oldInDraw = device->isInDraw; - ENTER_GL(); - for (i = 0; i < context->numDirtyEntries; ++i) + /* surface_internal_preload() requires a context to load the + * texture, so it will call context_acquire(). Set isInDraw to true + * to signal surface_internal_preload() that it has a context. */ + + /* FIXME: This is just broken. There's no guarantee whatsoever + * that the currently active context, if any, is appropriate for + * reading back the render target. We should probably call + * context_set_current(context) here and then rely on + * context_acquire() doing the right thing. */ + device->isInDraw = TRUE; + + /* Read the back buffer of the old drawable into the destination texture. */ + if (context->current_rt->texture_name_srgb) { - DWORD rep = context->dirtyArray[i]; - DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT); - BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1); - context->isStateDirty[idx] &= ~(1 << shift); - state_table[rep].apply(rep, device->stateBlock, context); + surface_internal_preload(context->current_rt, SRGB_BOTH); + } + else + { + surface_internal_preload(context->current_rt, SRGB_RGB); } - LEAVE_GL(); - context->numDirtyEntries = 0; /* This makes the whole list clean */ - context->last_was_blit = FALSE; - break; - case CTXUSAGE_BLIT: - SetupForBlit(device, context); - break; + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)context->current_rt, SFLAG_INDRAWABLE, FALSE); - default: - FIXME("Unexpected context usage requested\n"); + device->isInDraw = oldInDraw; + } } + + context->draw_buffer_dirty = TRUE; + context->current_rt = target; } /***************************************************************************** @@ -2256,14 +2211,15 @@ static void context_apply_state(struct wined3d_context *context, IWineD3DDeviceI * usage: Prepares the context for blitting, drawing or other actions * *****************************************************************************/ -struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurface *target, enum ContextUsage usage) +struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *target) { struct wined3d_context *current_context = context_get_current(); struct wined3d_context *context; - TRACE("device %p, target %p, usage %#x.\n", device, target, usage); + TRACE("device %p, target %p.\n", device, target); context = FindContext(device, target); + context_setup_target(device, context, target); context_enter(context); if (!context->valid) return context; @@ -2295,7 +2251,5 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurf } } - context_apply_state(context, device, usage); - return context; } diff --git a/reactos/dll/directx/wine/wined3d/cubetexture.c b/reactos/dll/directx/wine/wined3d/cubetexture.c index c5fa6ba280f..12acee26573 100644 --- a/reactos/dll/directx/wine/wined3d/cubetexture.c +++ b/reactos/dll/directx/wine/wined3d/cubetexture.c @@ -31,11 +31,12 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 { /* Override the IWineD3DResource Preload method. */ IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; + UINT sub_count = This->baseTexture.level_count * This->baseTexture.layer_count; IWineD3DDeviceImpl *device = This->resource.device; struct wined3d_context *context = NULL; - unsigned int i, j; BOOL srgb_mode; BOOL *dirty; + UINT i; switch (srgb) { @@ -66,25 +67,24 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 { /* No danger of recursive calls, context_acquire() sets isInDraw to true * when loading offscreen render targets into their texture. */ - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); } if (This->resource.format_desc->format == WINED3DFMT_P8_UINT || This->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < sub_count; ++i) { - for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++j) + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + + if (palette9_changed(surface)) { - if (palette9_changed((IWineD3DSurfaceImpl *)This->surfaces[j][i])) - { - TRACE("Reloading surface because the d3d8/9 palette was changed.\n"); - /* TODO: This is not necessarily needed with hw palettized texture support. */ - IWineD3DSurface_LoadLocation(This->surfaces[j][i], SFLAG_INSYSMEM, NULL); - /* Make sure the texture is reloaded because of the palette change, - * this kills performance though :( */ - IWineD3DSurface_ModifyLocation(This->surfaces[j][i], SFLAG_INTEXTURE, FALSE); - } + TRACE("Reloading surface %p because the d3d8/9 palette was changed.\n", surface); + /* TODO: This is not necessarily needed with hw palettized texture support. */ + IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, NULL); + /* Make sure the texture is reloaded because of the palette change, + * this kills performance though :( */ + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INTEXTURE, FALSE); } } } @@ -93,12 +93,9 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 * since the last load then reload the surfaces. */ if (*dirty) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < sub_count; ++i) { - for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++j) - { - IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); - } + IWineD3DSurface_LoadTexture((IWineD3DSurface *)This->baseTexture.sub_resources[i], srgb_mode); } } else @@ -114,26 +111,24 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This) { - unsigned int i, j; + UINT sub_count = This->baseTexture.level_count * This->baseTexture.layer_count; + UINT i; TRACE("(%p) : Cleaning up.\n", This); - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < sub_count; ++i) { - for (j = 0; j < 6; ++j) - { - IWineD3DSurface *surface = This->surfaces[j][i]; + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; - if (surface) - { - /* Clean out the texture name we gave to the surface so that the - * surface doesn't try and release it. */ - surface_set_texture_name(surface, 0, TRUE); - surface_set_texture_name(surface, 0, FALSE); - surface_set_texture_target(surface, 0); - IWineD3DSurface_SetContainer(surface, NULL); - IWineD3DSurface_Release(surface); - } + if (surface) + { + /* Clean out the texture name we gave to the surface so that the + * surface doesn't try and release it. */ + surface_set_texture_name(surface, 0, TRUE); + surface_set_texture_name(surface, 0, FALSE); + surface_set_texture_target(surface, 0); + IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL); + IWineD3DSurface_Release((IWineD3DSurface *)surface); } } basetexture_cleanup((IWineD3DBaseTexture *)This); @@ -207,21 +202,25 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { cubetexture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); } -static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) { - unsigned int i, j; +static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) +{ IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - TRACE("(%p)\n", This); + UINT sub_count = This->baseTexture.level_count * This->baseTexture.layer_count; + UINT i; + + TRACE("iface %p.\n", iface); /* Unload all the surfaces and reset the texture name. If UnLoad was called on the * surface before, this one will be a NOP and vice versa. Unloading an unloaded - * surface is fine - */ - for (i = 0; i < This->baseTexture.levels; i++) { - for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { - IWineD3DSurface_UnLoad(This->surfaces[j][i]); - surface_set_texture_name(This->surfaces[j][i], 0, TRUE); - surface_set_texture_name(This->surfaces[j][i], 0, FALSE); - } + * surface is fine. */ + + for (i = 0; i < sub_count; ++i) + { + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + + IWineD3DSurface_UnLoad((IWineD3DSurface *)surface); + surface_set_texture_name(surface, 0, TRUE); + surface_set_texture_name(surface, 0, FALSE); } basetexture_unload((IWineD3DBaseTexture *)iface); @@ -281,16 +280,19 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_BindTexture(IWineD3DCubeTexture *i TRACE("(%p) : relay to BaseTexture\n", This); hr = basetexture_bind((IWineD3DBaseTexture *)iface, srgb, &set_gl_texture_desc); - if (set_gl_texture_desc && SUCCEEDED(hr)) { - UINT i, j; - for (i = 0; i < This->baseTexture.levels; ++i) { - for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++j) { - if(This->baseTexture.is_srgb) { - surface_set_texture_name(This->surfaces[j][i], This->baseTexture.texture_srgb.name, TRUE); - } else { - surface_set_texture_name(This->surfaces[j][i], This->baseTexture.texture_rgb.name, FALSE); - } - } + if (set_gl_texture_desc && SUCCEEDED(hr)) + { + UINT sub_count = This->baseTexture.level_count * This->baseTexture.layer_count; + UINT i; + + for (i = 0; i < sub_count; ++i) + { + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + + if (This->baseTexture.is_srgb) + surface_set_texture_name(surface, This->baseTexture.texture_srgb.name, TRUE); + else + surface_set_texture_name(surface, This->baseTexture.texture_rgb.name, FALSE); } } @@ -314,82 +316,102 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface) /* ******************************************* IWineD3DCubeTexture IWineD3DCubeTexture parts follow ******************************************* */ -static HRESULT WINAPI IWineD3DCubeTextureImpl_GetLevelDesc(IWineD3DCubeTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) { - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; +static HRESULT WINAPI IWineD3DCubeTextureImpl_GetLevelDesc(IWineD3DCubeTexture *iface, + UINT level, WINED3DSURFACE_DESC *desc) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); - if (Level < This->baseTexture.levels) { - TRACE("(%p) level (%d)\n", This, Level); - return IWineD3DSurface_GetDesc(This->surfaces[0][Level], pDesc); + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - return WINED3DERR_INVALIDCALL; + + return IWineD3DSurface_GetDesc(surface, desc); } -static HRESULT WINAPI IWineD3DCubeTextureImpl_GetCubeMapSurface(IWineD3DCubeTexture *iface, WINED3DCUBEMAP_FACES FaceType, UINT Level, IWineD3DSurface** ppCubeMapSurface) { - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - HRESULT hr = WINED3DERR_INVALIDCALL; +static HRESULT WINAPI IWineD3DCubeTextureImpl_GetCubeMapSurface(IWineD3DCubeTexture *iface, + WINED3DCUBEMAP_FACES face, UINT level, IWineD3DSurface **surface) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *s; - if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { - *ppCubeMapSurface = This->surfaces[FaceType][Level]; - IWineD3DSurface_AddRef(*ppCubeMapSurface); + TRACE("iface %p, face %u, level %u, surface %p.\n", + iface, face, level, surface); - hr = WINED3D_OK; - } - if (WINED3D_OK == hr) { - TRACE("(%p) -> faceType(%d) level(%d) returning surface@%p\n", This, FaceType, Level, This->surfaces[FaceType][Level]); - } else { - WARN("(%p) level(%d) overflow Levels(%d) Or FaceType(%d)\n", This, Level, This->baseTexture.levels, FaceType); + if (!(s = (IWineD3DSurface *)basetexture_get_sub_resource(texture, face, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + IWineD3DSurface_AddRef(s); + *surface = s; + + TRACE("Returning surface %p.\n", *surface); + + return WINED3D_OK; } -static HRESULT WINAPI IWineD3DCubeTextureImpl_LockRect(IWineD3DCubeTexture *iface, WINED3DCUBEMAP_FACES FaceType, UINT Level, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { - HRESULT hr = WINED3DERR_INVALIDCALL; - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; +static HRESULT WINAPI IWineD3DCubeTextureImpl_LockRect(IWineD3DCubeTexture *iface, + WINED3DCUBEMAP_FACES face, UINT level, WINED3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; - if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { - hr = IWineD3DSurface_LockRect(This->surfaces[FaceType][Level], pLockedRect, pRect, Flags); - } + TRACE("iface %p, face %u, level %u, locked_rect %p, rect %s, flags %#x.\n", + iface, face, level, locked_rect, wine_dbgstr_rect(rect), flags); - if (WINED3D_OK == hr) { - TRACE("(%p) -> faceType(%d) level(%d) returning memory@%p success(%u)\n", This, FaceType, Level, pLockedRect->pBits, hr); - } else { - WARN("(%p) level(%d) overflow Levels(%d) Or FaceType(%d)\n", This, Level, This->baseTexture.levels, FaceType); + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, face, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + return IWineD3DSurface_LockRect(surface, locked_rect, rect, flags); } -static HRESULT WINAPI IWineD3DCubeTextureImpl_UnlockRect(IWineD3DCubeTexture *iface, WINED3DCUBEMAP_FACES FaceType, UINT Level) { - HRESULT hr = WINED3DERR_INVALIDCALL; - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; +static HRESULT WINAPI IWineD3DCubeTextureImpl_UnlockRect(IWineD3DCubeTexture *iface, + WINED3DCUBEMAP_FACES face, UINT level) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; - if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { - hr = IWineD3DSurface_UnlockRect(This->surfaces[FaceType][Level]); - } + TRACE("iface %p, face %u, level %u.\n", + iface, face, level); - if (WINED3D_OK == hr) { - TRACE("(%p) -> faceType(%d) level(%d) success(%u)\n", This, FaceType, Level, hr); - } else { - WARN("(%p) level(%d) overflow Levels(%d) Or FaceType(%d)\n", This, Level, This->baseTexture.levels, FaceType); + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, face, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + return IWineD3DSurface_UnlockRect(surface); } -static HRESULT WINAPI IWineD3DCubeTextureImpl_AddDirtyRect(IWineD3DCubeTexture *iface, WINED3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) { - HRESULT hr = WINED3DERR_INVALIDCALL; - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - This->baseTexture.texture_rgb.dirty = TRUE; - This->baseTexture.texture_srgb.dirty = TRUE; - TRACE("(%p) : dirtyfication of faceType(%d) Level (0)\n", This, FaceType); - if (FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { - surface_add_dirty_rect(This->surfaces[FaceType][0], pDirtyRect); - hr = WINED3D_OK; - } else { - WARN("(%p) overflow FaceType(%d)\n", This, FaceType); +static HRESULT WINAPI IWineD3DCubeTextureImpl_AddDirtyRect(IWineD3DCubeTexture *iface, + WINED3DCUBEMAP_FACES face, const RECT *dirty_rect) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurfaceImpl *surface; + + TRACE("iface %p, face %u, dirty_rect %s.\n", + iface, face, wine_dbgstr_rect(dirty_rect)); + + if (!(surface = (IWineD3DSurfaceImpl *)basetexture_get_sub_resource(texture, face, 0))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + texture->baseTexture.texture_rgb.dirty = TRUE; + texture->baseTexture.texture_srgb.dirty = TRUE; + surface_add_dirty_rect(surface, dirty_rect); + + return WINED3D_OK; } static const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl = @@ -433,7 +455,7 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); UINT pow2_edge_length; unsigned int i, j; UINT tmp_w; @@ -478,8 +500,8 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN texture->lpVtbl = &IWineD3DCubeTexture_Vtbl; - hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_CUBETEXTURE, - device, 0, usage, format_desc, pool, parent, parent_ops); + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, 6, levels, + WINED3DRTYPE_CUBETEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x\n", hr); @@ -510,7 +532,7 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN /* Generate all the surfaces. */ tmp_w = edge_length; - for (i = 0; i < texture->baseTexture.levels; ++i) + for (i = 0; i < texture->baseTexture.level_count; ++i) { /* Create the 6 faces. */ for (j = 0; j < 6; ++j) @@ -524,20 +546,22 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, }; + UINT idx = j * texture->baseTexture.level_count + i; + IWineD3DSurface *surface; hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_w, - format, usage, pool, i /* Level */, j, &texture->surfaces[j][i]); + format, usage, pool, i /* Level */, j, &surface); if (FAILED(hr)) { FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr); - texture->surfaces[j][i] = NULL; cubetexture_cleanup(texture); return hr; } - IWineD3DSurface_SetContainer(texture->surfaces[j][i], (IWineD3DBase *)texture); - TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[j][i]); - surface_set_texture_target(texture->surfaces[j][i], cube_targets[j]); + IWineD3DSurface_SetContainer(surface, (IWineD3DBase *)texture); + surface_set_texture_target((IWineD3DSurfaceImpl *)surface, cube_targets[j]); + texture->baseTexture.sub_resources[idx] = (IWineD3DResourceImpl *)surface; + TRACE("Created surface level %u @ %p.\n", i, surface); } tmp_w = max(1, tmp_w >> 1); } diff --git a/reactos/dll/directx/wine/wined3d/device.c b/reactos/dll/directx/wine/wined3d/device.c index 6682aa4635e..7eb9153fca9 100644 --- a/reactos/dll/directx/wine/wined3d/device.c +++ b/reactos/dll/directx/wine/wined3d/device.c @@ -34,7 +34,6 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->adapter->gl_info /* Define the default light parameters as specified by MSDN */ const WINED3DLIGHT WINED3D_default_light = { @@ -213,7 +212,8 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, else { TRACE("Stream %u isn't UP, %p\n", element->input_slot, This->stateBlock->streamSource[element->input_slot]); - data = buffer_get_memory(This->stateBlock->streamSource[element->input_slot], 0, &buffer_object); + data = buffer_get_memory(This->stateBlock->streamSource[element->input_slot], + &This->adapter->gl_info, &buffer_object); /* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets * (or rather offsets bigger than the vbo, because the pointer is unsigned), so use system memory @@ -224,7 +224,8 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, { WARN("loadBaseVertexIndex is < 0 (%d), not using vbos\n", This->stateBlock->loadBaseVertexIndex); buffer_object = 0; - data = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->streamSource[element->input_slot]); + data = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->streamSource[element->input_slot], + &This->adapter->gl_info); if ((UINT_PTR)data < -This->stateBlock->loadBaseVertexIndex * stride) { FIXME("System memory vertex data load offset is negative!\n"); @@ -305,6 +306,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, } } + This->num_buffer_queries = 0; if (!This->stateBlock->streamIsUP) { WORD map = stream_info->use_map; @@ -314,6 +316,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, { struct wined3d_stream_info_element *element; struct wined3d_buffer *buffer; + struct wined3d_event_query *query; if (!(map & 1)) continue; @@ -325,7 +328,13 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, if (buffer->buffer_object != element->buffer_object) { element->buffer_object = 0; - element->data = buffer_get_sysmem(buffer) + (ptrdiff_t)element->data; + element->data = buffer_get_sysmem(buffer, &This->adapter->gl_info) + (ptrdiff_t)element->data; + } + + query = ((struct wined3d_buffer *) buffer)->query; + if(query) + { + This->buffer_queries[This->num_buffer_queries++] = query; } } } @@ -334,7 +343,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, static void stream_info_element_from_strided(const struct wined3d_gl_info *gl_info, const struct WineDirect3DStridedData *strided, struct wined3d_stream_info_element *e) { - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(strided->format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(strided->format, gl_info); e->format_desc = format_desc; e->stride = strided->dwStride; e->data = strided->lpData; @@ -494,6 +503,95 @@ void device_preload_textures(IWineD3DDeviceImpl *device) } } +BOOL device_context_add(IWineD3DDeviceImpl *device, struct wined3d_context *context) +{ + struct wined3d_context **new_array; + + TRACE("Adding context %p.\n", context); + + if (!device->contexts) new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array)); + else new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts, sizeof(*new_array) * (device->numContexts + 1)); + + if (!new_array) + { + ERR("Failed to grow the context array.\n"); + return FALSE; + } + + new_array[device->numContexts++] = context; + device->contexts = new_array; + return TRUE; +} + +void device_context_remove(IWineD3DDeviceImpl *device, struct wined3d_context *context) +{ + struct wined3d_context **new_array; + BOOL found = FALSE; + UINT i; + + TRACE("Removing context %p.\n", context); + + for (i = 0; i < device->numContexts; ++i) + { + if (device->contexts[i] == context) + { + found = TRUE; + break; + } + } + + if (!found) + { + ERR("Context %p doesn't exist in context array.\n", context); + return; + } + + if (!--device->numContexts) + { + HeapFree(GetProcessHeap(), 0, device->contexts); + device->contexts = NULL; + return; + } + + memmove(&device->contexts[i], &device->contexts[i + 1], (device->numContexts - i) * sizeof(*device->contexts)); + new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts, device->numContexts * sizeof(*device->contexts)); + if (!new_array) + { + ERR("Failed to shrink context array. Oh well.\n"); + return; + } + + device->contexts = new_array; +} + +void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect) +{ + IWineD3DStateBlockImpl *stateblock = device->stateBlock; + WINED3DVIEWPORT *vp = &stateblock->viewport; + + SetRect(rect, vp->X, vp->Y, vp->X + vp->Width, vp->Y + vp->Height); + + if (stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) + { + IntersectRect(rect, rect, &stateblock->scissorRect); + } +} + +void device_switch_onscreen_ds(IWineD3DDeviceImpl *device, + struct wined3d_context *context, IWineD3DSurfaceImpl *depth_stencil) +{ + if (device->onscreen_depth_stencil) + { + surface_load_ds_location(device->onscreen_depth_stencil, context, SFLAG_DS_OFFSCREEN); + surface_modify_ds_location(device->onscreen_depth_stencil, SFLAG_DS_OFFSCREEN, + device->onscreen_depth_stencil->ds_current_size.cx, + device->onscreen_depth_stencil->ds_current_size.cy); + IWineD3DSurface_Release((IWineD3DSurface *)device->onscreen_depth_stencil); + } + device->onscreen_depth_stencil = depth_stencil; + IWineD3DSurface_AddRef((IWineD3DSurface *)device->onscreen_depth_stencil); +} + /********************************************************** * IUnknown parts follows **********************************************************/ @@ -540,9 +638,17 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { /* NOTE: You must release the parent if the object was created via a callback ** ***************************/ - if (!list_empty(&This->resources)) { + if (!list_empty(&This->resources)) + { + IWineD3DResourceImpl *resource; FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This); - dumpResources(&This->resources); + + LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) + { + WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource); + FIXME("Leftover resource %p with type %s (%#x).\n", + resource, debug_d3dresourcetype(type), type); + } } if(This->contexts) ERR("Context array not freed!\n"); @@ -760,6 +866,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice * { struct wined3d_rendertarget_view *object; + TRACE("iface %p, resource %p, parent %p, rendertarget_view %p.\n", + iface, resource, parent, rendertarget_view); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { @@ -767,12 +876,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice * return E_OUTOFMEMORY; } - object->vtbl = &wined3d_rendertarget_view_vtbl; - object->refcount = 1; - IWineD3DResource_AddRef(resource); - object->resource = resource; - object->parent = parent; + wined3d_rendertarget_view_init(object, resource, parent); + TRACE("Created render target view %p.\n", object); *rendertarget_view = (IWineD3DRendertargetView *)object; return WINED3D_OK; @@ -1030,11 +1136,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice return WINED3D_OK; } -static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */ - DWORD fvf, WINED3DVERTEXELEMENT** ppVertexElements) { +struct wined3d_fvf_convert_state +{ + const struct wined3d_gl_info *gl_info; + WINED3DVERTEXELEMENT *elements; + UINT offset; + UINT idx; +}; + +static void append_decl_element(struct wined3d_fvf_convert_state *state, + WINED3DFORMAT format, WINED3DDECLUSAGE usage, UINT usage_idx) +{ + WINED3DVERTEXELEMENT *elements = state->elements; + const struct wined3d_format_desc *format_desc; + UINT offset = state->offset; + UINT idx = state->idx; + + elements[idx].format = format; + elements[idx].input_slot = 0; + elements[idx].offset = offset; + elements[idx].output_slot = 0; + elements[idx].method = WINED3DDECLMETHOD_DEFAULT; + elements[idx].usage = usage; + elements[idx].usage_idx = usage_idx; + + format_desc = getFormatDescEntry(format, state->gl_info); + state->offset += format_desc->component_count * format_desc->component_size; + ++state->idx; +} - unsigned int idx, idx2; - unsigned int offset; +static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */ + DWORD fvf, WINED3DVERTEXELEMENT **ppVertexElements) +{ + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; BOOL has_pos = (fvf & WINED3DFVF_POSITION_MASK) != 0; BOOL has_blend = (fvf & WINED3DFVF_XYZB5) > WINED3DFVF_XYZRHW; BOOL has_blend_idx = has_blend && @@ -1048,9 +1182,9 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT; DWORD texcoords = (fvf & 0xFFFF0000) >> 16; - WINED3DVERTEXELEMENT *elements = NULL; - + struct wined3d_fvf_convert_state state; unsigned int size; + unsigned int idx; DWORD num_blends = 1 + (((fvf & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1); if (has_blend_idx) num_blends--; @@ -1058,112 +1192,84 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal + has_psize + has_diffuse + has_specular + num_textures; - /* convert the declaration */ - elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WINED3DVERTEXELEMENT)); - if (!elements) return ~0U; + state.gl_info = gl_info; + state.elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*state.elements)); + if (!state.elements) return ~0U; + state.offset = 0; + state.idx = 0; - idx = 0; - if (has_pos) { - if (!has_blend && (fvf & WINED3DFVF_XYZRHW)) { - elements[idx].format = WINED3DFMT_R32G32B32A32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_POSITIONT; - } - else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW) { - elements[idx].format = WINED3DFMT_R32G32B32A32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_POSITION; - } - else { - elements[idx].format = WINED3DFMT_R32G32B32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_POSITION; - } - elements[idx].usage_idx = 0; - idx++; - } - if (has_blend && (num_blends > 0)) { - if (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2) && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)) - elements[idx].format = WINED3DFMT_B8G8R8A8_UNORM; - else { - switch(num_blends) { - case 1: elements[idx].format = WINED3DFMT_R32_FLOAT; break; - case 2: elements[idx].format = WINED3DFMT_R32G32_FLOAT; break; - case 3: elements[idx].format = WINED3DFMT_R32G32B32_FLOAT; break; - case 4: elements[idx].format = WINED3DFMT_R32G32B32A32_FLOAT; break; + if (has_pos) + { + if (!has_blend && (fvf & WINED3DFVF_XYZRHW)) + append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITIONT, 0); + else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW) + append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITION, 0); + else + append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_POSITION, 0); + } + + if (has_blend && (num_blends > 0)) + { + if ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)) + append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDWEIGHT, 0); + else + { + switch (num_blends) + { + case 1: + append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0); + break; + case 2: + append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0); + break; + case 3: + append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0); + break; + case 4: + append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0); + break; default: ERR("Unexpected amount of blend values: %u\n", num_blends); } } - elements[idx].usage = WINED3DDECLUSAGE_BLENDWEIGHT; - elements[idx].usage_idx = 0; - idx++; - } - if (has_blend_idx) { - if (fvf & WINED3DFVF_LASTBETA_UBYTE4 || - (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2) && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))) - elements[idx].format = WINED3DFMT_R8G8B8A8_UINT; + } + + if (has_blend_idx) + { + if ((fvf & WINED3DFVF_LASTBETA_UBYTE4) + || ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))) + append_decl_element(&state, WINED3DFMT_R8G8B8A8_UINT, WINED3DDECLUSAGE_BLENDINDICES, 0); else if (fvf & WINED3DFVF_LASTBETA_D3DCOLOR) - elements[idx].format = WINED3DFMT_B8G8R8A8_UNORM; + append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDINDICES, 0); else - elements[idx].format = WINED3DFMT_R32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_BLENDINDICES; - elements[idx].usage_idx = 0; - idx++; - } - if (has_normal) { - elements[idx].format = WINED3DFMT_R32G32B32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_NORMAL; - elements[idx].usage_idx = 0; - idx++; - } - if (has_psize) { - elements[idx].format = WINED3DFMT_R32_FLOAT; - elements[idx].usage = WINED3DDECLUSAGE_PSIZE; - elements[idx].usage_idx = 0; - idx++; - } - if (has_diffuse) { - elements[idx].format = WINED3DFMT_B8G8R8A8_UNORM; - elements[idx].usage = WINED3DDECLUSAGE_COLOR; - elements[idx].usage_idx = 0; - idx++; - } - if (has_specular) { - elements[idx].format = WINED3DFMT_B8G8R8A8_UNORM; - elements[idx].usage = WINED3DDECLUSAGE_COLOR; - elements[idx].usage_idx = 1; - idx++; - } - for (idx2 = 0; idx2 < num_textures; idx2++) { - unsigned int numcoords = (texcoords >> (idx2*2)) & 0x03; - switch (numcoords) { + append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDINDICES, 0); + } + + if (has_normal) append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_NORMAL, 0); + if (has_psize) append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_PSIZE, 0); + if (has_diffuse) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 0); + if (has_specular) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 1); + + for (idx = 0; idx < num_textures; ++idx) + { + switch ((texcoords >> (idx * 2)) & 0x03) + { case WINED3DFVF_TEXTUREFORMAT1: - elements[idx].format = WINED3DFMT_R32_FLOAT; + append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx); break; case WINED3DFVF_TEXTUREFORMAT2: - elements[idx].format = WINED3DFMT_R32G32_FLOAT; + append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx); break; case WINED3DFVF_TEXTUREFORMAT3: - elements[idx].format = WINED3DFMT_R32G32B32_FLOAT; + append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx); break; case WINED3DFVF_TEXTUREFORMAT4: - elements[idx].format = WINED3DFMT_R32G32B32A32_FLOAT; + append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx); break; } - elements[idx].usage = WINED3DDECLUSAGE_TEXCOORD; - elements[idx].usage_idx = idx2; - idx++; - } - - /* Now compute offsets, and initialize the rest of the fields */ - for (idx = 0, offset = 0; idx < size; ++idx) - { - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(elements[idx].format, &This->adapter->gl_info); - elements[idx].input_slot = 0; - elements[idx].method = WINED3DDECLMETHOD_DEFAULT; - elements[idx].offset = offset; - offset += format_desc->component_count * format_desc->component_size; } - *ppVertexElements = elements; + *ppVertexElements = state.elements; return size; } @@ -1282,35 +1388,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DW IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DPaletteImpl *object; HRESULT hr; - TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent); - /* Create the new object */ - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl)); - if(!object) { - ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n"); - return E_OUTOFMEMORY; - } + TRACE("iface %p, flags %#x, entries %p, palette %p, parent %p.\n", + iface, Flags, PalEnt, Palette, Parent); - object->lpVtbl = &IWineD3DPalette_Vtbl; - object->ref = 1; - object->Flags = Flags; - object->parent = Parent; - object->device = This; - object->palNumEntries = IWineD3DPaletteImpl_Size(Flags); - object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion)); - - if(!object->hpal) { - HeapFree( GetProcessHeap(), 0, object); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Failed to allocate palette memory.\n"); return E_OUTOFMEMORY; } - hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt); - if(FAILED(hr)) { - IWineD3DPalette_Release((IWineD3DPalette *) object); + hr = wined3d_palette_init(object, This, Flags, PalEnt, Parent); + if (FAILED(hr)) + { + WARN("Failed to initialize palette, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); return hr; } - *Palette = (IWineD3DPalette *) object; + TRACE("Created palette %p.\n", object); + *Palette = (IWineD3DPalette *)object; return WINED3D_OK; } @@ -1429,6 +1527,30 @@ static void destroy_dummy_textures(IWineD3DDeviceImpl *device, const struct wine memset(device->dummyTextureName, 0, gl_info->limits.textures * sizeof(*device->dummyTextureName)); } +static HRESULT WINAPI IWineD3DDeviceImpl_AcquireFocusWindow(IWineD3DDevice *iface, HWND window) +{ + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface; + + if (!wined3d_register_window(window, device)) + { + ERR("Failed to register window %p.\n", window); + return E_FAIL; + } + + device->focus_window = window; + SetForegroundWindow(window); + + return WINED3D_OK; +} + +static void WINAPI IWineD3DDeviceImpl_ReleaseFocusWindow(IWineD3DDevice *iface) +{ + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface; + + if (device->focus_window) wined3d_unregister_window(device->focus_window); + device->focus_window = NULL; +} + static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) { @@ -1445,17 +1567,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, if(This->d3d_initialized) return WINED3DERR_INVALIDCALL; if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL; - if (!pPresentationParameters->Windowed) - { - This->focus_window = This->createParms.hFocusWindow; - if (!This->focus_window) This->focus_window = pPresentationParameters->hDeviceWindow; - if (!wined3d_register_window(This->focus_window, This)) - { - ERR("Failed to register window %p.\n", This->focus_window); - return E_FAIL; - } - } - TRACE("(%p) : Creating stateblock\n", This); /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */ hr = IWineD3DDevice_CreateStateBlock(iface, @@ -1471,7 +1582,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock); This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(IWineD3DSurface *) * gl_info->limits.buffers); + sizeof(*This->render_targets) * gl_info->limits.buffers); This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * gl_info->limits.buffers); @@ -1509,8 +1620,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, } } - if (This->focus_window) SetFocus(This->focus_window); - /* Setup the implicit swapchain. This also initializes a context. */ TRACE("Creating implicit swapchain\n"); hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent, @@ -1529,21 +1638,22 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, } This->swapchains[0] = (IWineD3DSwapChain *) swapchain; - if(swapchain->backBuffer && swapchain->backBuffer[0]) { - TRACE("Setting rendertarget to %p\n", swapchain->backBuffer); - This->render_targets[0] = swapchain->backBuffer[0]; + if (swapchain->back_buffers && swapchain->back_buffers[0]) + { + TRACE("Setting rendertarget to %p.\n", swapchain->back_buffers); + This->render_targets[0] = swapchain->back_buffers[0]; } - else { - TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer); - This->render_targets[0] = swapchain->frontBuffer; + else + { + TRACE("Setting rendertarget to %p.\n", swapchain->front_buffer); + This->render_targets[0] = swapchain->front_buffer; } - IWineD3DSurface_AddRef(This->render_targets[0]); + IWineD3DSurface_AddRef((IWineD3DSurface *)This->render_targets[0]); /* Depth Stencil support */ - This->stencilBufferTarget = This->auto_depth_stencil_buffer; - if (NULL != This->stencilBufferTarget) { - IWineD3DSurface_AddRef(This->stencilBufferTarget); - } + This->depth_stencil = This->auto_depth_stencil; + if (This->depth_stencil) + IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil); hr = This->shader_backend->shader_alloc_private(iface); if(FAILED(hr)) { @@ -1566,7 +1676,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, /* Setup all the devices defaults */ IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock); - context = context_acquire(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, swapchain->front_buffer); create_dummy_textures(This); @@ -1583,10 +1693,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, This->offscreenBuffer = GL_COLOR_ATTACHMENT0; break; - case ORM_PBUFFER: - This->offscreenBuffer = GL_BACK; - break; - case ORM_BACKBUFFER: { if (context_get_current()->aux_buffers > 0) @@ -1645,7 +1751,6 @@ err_out: if (This->shader_priv) { This->shader_backend->shader_free_private(iface); } - if (This->focus_window) wined3d_unregister_window(This->focus_window); return hr; } @@ -1702,7 +1807,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, /* I don't think that the interface guarantees that the device is destroyed from the same thread * it was created. Thus make sure a context is active for the glDelete* calls */ - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); gl_info = context->gl_info; if(This->logo_surface) IWineD3DSurface_Release(This->logo_surface); @@ -1720,9 +1825,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, } } - /* Delete the pbuffer context if there is any */ - if(This->pbufferContext) context_destroy(This, This->pbufferContext); - /* Delete the mouse cursor texture */ if(This->cursorTexture) { ENTER_GL(); @@ -1781,26 +1883,33 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, This->shader_backend->shader_free_private(iface); /* Release the buffers (with sanity checks)*/ - TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget); - if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){ - if(This->auto_depth_stencil_buffer != This->stencilBufferTarget) - FIXME("(%p) Something's still holding the stencilBufferTarget\n",This); + if (This->onscreen_depth_stencil) + { + IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil); + This->onscreen_depth_stencil = NULL; } - This->stencilBufferTarget = NULL; - TRACE("Releasing the render target at %p\n", This->render_targets[0]); - if(IWineD3DSurface_Release(This->render_targets[0]) >0){ - /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */ + TRACE("Releasing the depth stencil buffer at %p\n", This->depth_stencil); + if (This->depth_stencil && IWineD3DSurface_Release((IWineD3DSurface *)This->depth_stencil)) + { + if (This->auto_depth_stencil != This->depth_stencil) + FIXME("(%p) Something is still holding the depth/stencil buffer.\n",This); } + This->depth_stencil = NULL; + + TRACE("Releasing the render target at %p\n", This->render_targets[0]); + IWineD3DSurface_Release((IWineD3DSurface *)This->render_targets[0]); + TRACE("Setting rendertarget to NULL\n"); This->render_targets[0] = NULL; - if (This->auto_depth_stencil_buffer) { - if (IWineD3DSurface_Release(This->auto_depth_stencil_buffer) > 0) + if (This->auto_depth_stencil) + { + if (IWineD3DSurface_Release((IWineD3DSurface *)This->auto_depth_stencil)) { FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This); } - This->auto_depth_stencil_buffer = NULL; + This->auto_depth_stencil = NULL; } context_release(context); @@ -1828,8 +1937,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, This->d3d_initialized = FALSE; - if (This->focus_window) wined3d_unregister_window(This->focus_window); - return WINED3D_OK; } @@ -1867,8 +1974,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, U const WINED3DDISPLAYMODE* pMode) { DEVMODEW devmode; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_format_desc *format_desc = getFormatDescEntry(pMode->Format, &This->adapter->gl_info); LONG ret; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(pMode->Format, &This->adapter->gl_info); RECT clip_rc; TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format)); @@ -2982,7 +3089,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI( TRACE("(iface %p, dstData %p, start %d, count %d)\n", iface, dstData, start, count); - if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0) + if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= 0) return WINED3DERR_INVALIDCALL; memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4); @@ -3469,9 +3576,8 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn /* We might access VBOs from this code, so hold the lock */ ENTER_GL(); - if (dest->resource.allocatedMemory == NULL) { - buffer_get_sysmem(dest); - } + if (!dest->resource.allocatedMemory) + buffer_get_sysmem(dest, gl_info); /* Get a pointer into the destination vbo(create one if none exists) and * write correct opengl data into it. It's cheap and allows us to run drawStridedFast @@ -3518,7 +3624,7 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn FIXME("Clipping is broken and disabled for now\n"); } } else doClip = FALSE; - dest_ptr = ((char *) buffer_get_sysmem(dest)) + dwDestIndex * get_flexible_vertex_size(DestFVF); + dest_ptr = ((char *)buffer_get_sysmem(dest, gl_info)) + dwDestIndex * get_flexible_vertex_size(DestFVF); IWineD3DDevice_GetTransform( (IWineD3DDevice *) This, WINED3DTS_VIEW, @@ -3794,6 +3900,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; struct wined3d_stream_info stream_info; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP; HRESULT hr; @@ -3805,7 +3912,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, } /* Need any context to write to the vbo. */ - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); + gl_info = context->gl_info; /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP * control the streamIsUP flag, thus restore it afterwards. @@ -3832,7 +3940,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, { struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; e->buffer_object = 0; - e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb)); + e->data = (BYTE *)((ULONG_PTR)e->data + (ULONG_PTR)buffer_get_sysmem(vb, gl_info)); ENTER_GL(); GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object)); vb->buffer_object = 0; @@ -4218,7 +4326,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) return WINED3DERR_INVALIDCALL; } - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ wglFlush(); /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever @@ -4250,18 +4358,81 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, return WINED3D_OK; } +static BOOL is_full_clear(IWineD3DSurfaceImpl *target, const RECT *draw_rect, const RECT *clear_rect) +{ + /* partial draw rect */ + if (draw_rect->left || draw_rect->top + || draw_rect->right < target->currentDesc.Width + || draw_rect->bottom < target->currentDesc.Height) + return FALSE; + + /* partial clear rect */ + if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0 + || clear_rect->right < target->currentDesc.Width + || clear_rect->bottom < target->currentDesc.Height)) + return FALSE; + + return TRUE; +} + +static void prepare_ds_clear(IWineD3DSurfaceImpl *ds, struct wined3d_context *context, + DWORD location, const RECT *draw_rect, UINT rect_count, const RECT *clear_rect) +{ + RECT current_rect, r; + + if (ds->Flags & location) + SetRect(¤t_rect, 0, 0, + ds->ds_current_size.cx, + ds->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); + + IntersectRect(&r, draw_rect, ¤t_rect); + if (EqualRect(&r, draw_rect)) + { + /* current_rect ⊇ draw_rect, modify only. */ + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); + return; + } + + if (EqualRect(&r, ¤t_rect)) + { + /* draw_rect ⊇ current_rect, test if we're doing a full clear. */ + + if (!clear_rect) + { + /* Full clear, modify only. */ + surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom); + return; + } + + IntersectRect(&r, draw_rect, clear_rect); + if (EqualRect(&r, draw_rect)) + { + /* clear_rect ⊇ draw_rect, modify only. */ + surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom); + return; + } + } + + /* Full load. */ + surface_load_ds_location(ds, context, location); + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); +} + /* Not called from the VTable (internal subroutine) */ -HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, - CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color, - float Z, DWORD Stencil) { +HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, + const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) +{ + const RECT *clear_rect = (Count > 0 && pRects) ? (const RECT *)pRects : NULL; + IWineD3DSurfaceImpl *depth_stencil = This->depth_stencil; GLbitfield glMask = 0; unsigned int i; - WINED3DRECT curRect; - RECT vp_rect; - const WINED3DVIEWPORT *vp = &This->stateBlock->viewport; UINT drawable_width, drawable_height; - IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget; struct wined3d_context *context; + RECT draw_rect; + + device_get_draw_rect(This, &draw_rect); /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true @@ -4272,132 +4443,119 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother * checking all this if the dest surface is in the drawable anyway. */ - if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) { - while(1) { - if(vp->X != 0 || vp->Y != 0 || - vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - break; - } - if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && ( - This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 || - This->stateBlock->scissorRect.right < target->currentDesc.Width || - This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - break; - } - if(Count > 0 && pRects && ( - pRects[0].x1 > 0 || pRects[0].y1 > 0 || - pRects[0].x2 < target->currentDesc.Width || - pRects[0].y2 < target->currentDesc.Height)) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - break; - } - break; - } + if (Flags & WINED3DCLEAR_TARGET && !(target->Flags & SFLAG_INDRAWABLE)) + { + if (!is_full_clear(target, &draw_rect, clear_rect)) + IWineD3DSurface_LoadLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, NULL); } - context = context_acquire(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR); + context = context_acquire(This, target); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping clear.\n"); + return WINED3D_OK; + } + + context_apply_clear_state(context, This, target, depth_stencil); target->get_drawable_size(context, &drawable_width, &drawable_height); ENTER_GL(); /* Only set the values up once, as they are not changing */ - if (Flags & WINED3DCLEAR_STENCIL) { + if (Flags & WINED3DCLEAR_STENCIL) + { + if (context->gl_info->supported[EXT_STENCIL_TWO_SIDE]) + { + glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE)); + } + glStencilMask(~0U); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK)); glClearStencil(Stencil); checkGLcall("glClearStencil"); glMask = glMask | GL_STENCIL_BUFFER_BIT; - glStencilMask(0xFFFFFFFF); } - if (Flags & WINED3DCLEAR_ZBUFFER) { + if (Flags & WINED3DCLEAR_ZBUFFER) + { DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + + if (location == SFLAG_DS_ONSCREEN && depth_stencil != This->onscreen_depth_stencil) + device_switch_onscreen_ds(This, context, depth_stencil); + prepare_ds_clear(depth_stencil, context, location, &draw_rect, Count, clear_rect); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)depth_stencil, SFLAG_INDRAWABLE, TRUE); + glDepthMask(GL_TRUE); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE)); glClearDepth(Z); checkGLcall("glClearDepth"); glMask = glMask | GL_DEPTH_BUFFER_BIT; - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE)); - - if (vp->X != 0 || vp->Y != 0 || - vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) { - surface_load_ds_location(This->stencilBufferTarget, context, location); - } - else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && ( - This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 || - This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width || - This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) { - surface_load_ds_location(This->stencilBufferTarget, context, location); - } - else if (Count > 0 && pRects && ( - pRects[0].x1 > 0 || pRects[0].y1 > 0 || - pRects[0].x2 < depth_stencil->currentDesc.Width || - pRects[0].y2 < depth_stencil->currentDesc.Height)) { - surface_load_ds_location(This->stencilBufferTarget, context, location); - } } - if (Flags & WINED3DCLEAR_TARGET) { - TRACE("Clearing screen with glClear to color %x\n", Color); - glClearColor(D3DCOLOR_R(Color), - D3DCOLOR_G(Color), - D3DCOLOR_B(Color), - D3DCOLOR_A(Color)); - checkGLcall("glClearColor"); + if (Flags & WINED3DCLEAR_TARGET) + { + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); - /* Clear ALL colors! */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3)); + glClearColor(D3DCOLOR_R(Color), D3DCOLOR_G(Color), D3DCOLOR_B(Color), D3DCOLOR_A(Color)); + checkGLcall("glClearColor"); glMask = glMask | GL_COLOR_BUFFER_BIT; } - vp_rect.left = vp->X; - vp_rect.top = vp->Y; - vp_rect.right = vp->X + vp->Width; - vp_rect.bottom = vp->Y + vp->Height; - if (!(Count > 0 && pRects)) { - if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) { - IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect); - } + if (!clear_rect) + { if (context->render_offscreen) { - glScissor(vp_rect.left, vp_rect.top, - vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top); - } else { - glScissor(vp_rect.left, drawable_height - vp_rect.bottom, - vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top); + glScissor(draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top); + } + else + { + glScissor(draw_rect.left, drawable_height - draw_rect.bottom, + draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top); } checkGLcall("glScissor"); glClear(glMask); checkGLcall("glClear"); - } else { - /* Now process each rect in turn */ - for (i = 0; i < Count; i++) { + } + else + { + RECT current_rect; + + /* Now process each rect in turn. */ + for (i = 0; i < Count; ++i) + { /* Note gl uses lower left, width/height */ - IntersectRect((RECT *)&curRect, &vp_rect, (const RECT *)&pRects[i]); - if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) { - IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect); - } - TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, - pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2, - curRect.x1, (target->currentDesc.Height - curRect.y2), - curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); + IntersectRect(¤t_rect, &draw_rect, &clear_rect[i]); + + TRACE("clear_rect[%u] %s, current_rect %s.\n", i, + wine_dbgstr_rect(&clear_rect[i]), + wine_dbgstr_rect(¤t_rect)); /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently. * The rectangle is not cleared, no error is returned, but further rectanlges are - * still cleared if they are valid - */ - if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) { - TRACE("Rectangle with negative dimensions, ignoring\n"); + * still cleared if they are valid. */ + if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom) + { + TRACE("Rectangle with negative dimensions, ignoring.\n"); continue; } if (context->render_offscreen) { - glScissor(curRect.x1, curRect.y1, - curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); - } else { - glScissor(curRect.x1, drawable_height - curRect.y2, - curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); + glScissor(current_rect.left, current_rect.top, + current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); + } + else + { + glScissor(current_rect.left, drawable_height - current_rect.bottom, + current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); } checkGLcall("glScissor"); @@ -4406,52 +4564,33 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa } } - /* Restore the old values (why..?) */ - if (Flags & WINED3DCLEAR_STENCIL) { - glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]); - } - if (Flags & WINED3DCLEAR_TARGET) { - DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE]; - glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, - mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, - mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, - mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE); - - /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists, - * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it - */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); - } - if (Flags & WINED3DCLEAR_ZBUFFER) { - /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */ - DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; - surface_modify_ds_location(This->stencilBufferTarget, location); - } - LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + if (wined3d_settings.strict_draw_ordering || ((target->Flags & SFLAG_SWAPCHAIN) + && ((IWineD3DSwapChainImpl *)target->container)->front_buffer == target)) + wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects, - DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) { +static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, + const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0]; TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This, Count, pRects, Flags, Color, Z, Stencil); - if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) { + if (Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && !This->depth_stencil) + { WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n"); /* TODO: What about depth stencil buffers without stencil bits? */ return WINED3DERR_INVALIDCALL; } - return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil); + return IWineD3DDeviceImpl_ClearSurface(This, This->render_targets[0], Count, pRects, Flags, Color, Z, Stencil); } /***** @@ -5083,71 +5222,58 @@ static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) return 0.0f; } -static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - /** TODO: remove casts to IWineD3DSurfaceImpl - * NOTE: move code to surface to accomplish this - ****************************************/ - IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface; - IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)pDestinationSurface; - int srcWidth, srcHeight; - unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight; - WINED3DFORMAT destFormat, srcFormat; - UINT destSize; - int srcLeft, destLeft, destTop; - WINED3DPOOL srcPool, destPool; - int offset = 0; - int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */ - const struct GlPixelFormatDesc *src_format_desc, *dst_format_desc; - GLenum dummy; - DWORD sampler; - int bpp; - CONVERT_TYPES convert = NO_CONVERSION; +static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, + IWineD3DSurface *src_surface, const RECT *src_rect, + IWineD3DSurface *dst_surface, const POINT *dst_point) +{ + IWineD3DSurfaceImpl *src_impl = (IWineD3DSurfaceImpl *)src_surface; + IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)dst_surface; + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_format_desc *src_format; + const struct wined3d_format_desc *dst_format; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; + const unsigned char *data; + UINT update_w, update_h; + CONVERT_TYPES convert; + UINT src_w, src_h; + UINT dst_x, dst_y; + DWORD sampler; + struct wined3d_format_desc desc; - WINED3DSURFACE_DESC winedesc; - - TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); - - IWineD3DSurface_GetDesc(pSourceSurface, &winedesc); - srcSurfaceWidth = winedesc.width; - srcSurfaceHeight = winedesc.height; - srcPool = winedesc.pool; - srcFormat = winedesc.format; - - IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); - destSurfaceWidth = winedesc.width; - destSurfaceHeight = winedesc.height; - destPool = winedesc.pool; - destFormat = winedesc.format; - destSize = winedesc.size; + TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n", + iface, src_surface, wine_dbgstr_rect(src_rect), + dst_surface, wine_dbgstr_point(dst_point)); - if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){ - WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface); + if (src_impl->resource.pool != WINED3DPOOL_SYSTEMMEM || dst_impl->resource.pool != WINED3DPOOL_DEFAULT) + { + WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", + src_surface, dst_surface); return WINED3DERR_INVALIDCALL; } - /* This call loads the opengl surface directly, instead of copying the surface to the - * destination's sysmem copy. If surface conversion is needed, use BltFast instead to - * copy in sysmem and use regular surface loading. - */ - d3dfmt_get_conv(dst_impl, FALSE, TRUE, &dummy, &dummy, &dummy, &convert, &bpp, FALSE); - if(convert != NO_CONVERSION) { - return IWineD3DSurface_BltFast(pDestinationSurface, - pDestPoint ? pDestPoint->x : 0, - pDestPoint ? pDestPoint->y : 0, - pSourceSurface, pSourceRect, 0); + src_format = src_impl->resource.format_desc; + dst_format = dst_impl->resource.format_desc; + + if (src_format->format != dst_format->format) + { + WARN("Source and destination surfaces should have the same format.\n"); + return WINED3DERR_INVALIDCALL; } - if (destFormat == WINED3DFMT_UNKNOWN) { - TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This); - IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat); + dst_x = dst_point ? dst_point->x : 0; + dst_y = dst_point ? dst_point->y : 0; - /* Get the update surface description */ - IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); - } + /* This call loads the OpenGL surface directly, instead of copying the + * surface to the destination's sysmem copy. If surface conversion is + * needed, use BltFast instead to copy in sysmem and use regular surface + * loading. */ + d3dfmt_get_conv(dst_impl, FALSE, TRUE, &desc, &convert); + if (convert != NO_CONVERSION || desc.convert) + return IWineD3DSurface_BltFast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0); - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); + gl_info = context->gl_info; ENTER_GL(); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); @@ -5155,92 +5281,79 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, LEAVE_GL(); /* Make sure the surface is loaded and up to date */ - surface_internal_preload(pDestinationSurface, SRGB_RGB); - IWineD3DSurface_BindTexture(pDestinationSurface, FALSE); + surface_internal_preload(dst_impl, SRGB_RGB); + IWineD3DSurface_BindTexture(dst_surface, FALSE); - src_format_desc = ((IWineD3DSurfaceImpl *)pSrcSurface)->resource.format_desc; - dst_format_desc = dst_impl->resource.format_desc; + src_w = src_impl->currentDesc.Width; + src_h = src_impl->currentDesc.Height; + update_w = src_rect ? src_rect->right - src_rect->left : src_w; + update_h = src_rect ? src_rect->bottom - src_rect->top : src_h; - /* this needs to be done in lines if the sourceRect != the sourceWidth */ - srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth; - srcHeight = pSourceRect ? pSourceRect->bottom - pSourceRect->top : srcSurfaceHeight; - srcLeft = pSourceRect ? pSourceRect->left : 0; - destLeft = pDestPoint ? pDestPoint->x : 0; - destTop = pDestPoint ? pDestPoint->y : 0; - - - /* This function doesn't support compressed textures - the pitch is just bytesPerPixel * width */ - if(srcWidth != srcSurfaceWidth || srcLeft ){ - rowoffset = srcSurfaceWidth * src_format_desc->byte_count; - offset += srcLeft * src_format_desc->byte_count; - /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */ - } - /* TODO DXT formats */ - - if(pSourceRect != NULL && pSourceRect->top != 0){ - offset += pSourceRect->top * srcSurfaceWidth * src_format_desc->byte_count; - } - TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n", - This, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat, - dst_format_desc->glType, IWineD3DSurface_GetData(pSourceSurface), offset); - - /* Sanity check */ - if (IWineD3DSurface_GetData(pSourceSurface) == NULL) { - - /* need to lock the surface to get the data */ - FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n"); - } + data = IWineD3DSurface_GetData(src_surface); + if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n"); ENTER_GL(); - /* TODO: Cube and volume support */ - if(rowoffset != 0){ - /* not a whole row so we have to do it a line at a time */ - int j; - - /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */ - const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset; + if (dst_format->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + UINT row_length = (update_w / src_format->block_width) * src_format->block_byte_count; + UINT row_count = update_h / src_format->block_height; + UINT src_pitch = IWineD3DSurface_GetPitch(src_surface); - for (j = destTop; j < (srcHeight + destTop); ++j) + if (src_rect) { - glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, j, - srcWidth, 1, dst_format_desc->glFormat, dst_format_desc->glType,data); - data += rowoffset; + data += (src_rect->top / src_format->block_height) * src_pitch; + data += (src_rect->left / src_format->block_width) * src_format->block_byte_count; } - } else { /* Full width, so just write out the whole texture */ - const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset; + TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, " + "format %#x, image_size %#x, data %p.\n", dst_impl->texture_target, dst_impl->texture_level, + dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data); - if (dst_format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + if (row_length == src_pitch) { - if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) - { - /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */ - FIXME("Updating part of a compressed texture is not supported.\n"); - } - if (destFormat != srcFormat) - { - FIXME("Updating mixed format compressed textures is not supported.\n"); - } - else + GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level, + dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data)); + } + else + { + UINT row, y; + + /* glCompressedTexSubImage2DARB() ignores pixel store state, so we + * can't use the unpack row length like below. */ + for (row = 0, y = dst_y; row < row_count; ++row) { - GL_EXTCALL(glCompressedTexImage2DARB(dst_impl->texture_target, dst_impl->texture_level, - dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data)); + GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level, + dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data)); + y += src_format->block_height; + data += src_pitch; } } - else + checkGLcall("glCompressedTexSubImage2DARB"); + } + else + { + if (src_rect) { - glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, destTop, - srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, data); + data += src_rect->top * src_w * src_format->byte_count; + data += src_rect->left * src_format->byte_count; } - } - checkGLcall("glTexSubImage2D"); + + TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n", + dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y, + update_w, update_h, dst_format->glFormat, dst_format->glType, data); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w); + glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y, + update_w, update_h, dst_format->glFormat, dst_format->glType, data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + checkGLcall("glTexSubImage2D"); + } LEAVE_GL(); context_release(context); - IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE); + IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INTEXTURE, TRUE); sampler = This->rev_tex_unit_map[0]; if (sampler != WINED3D_UNMAPPED_STAGE) { @@ -5370,68 +5483,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT return WINED3DERR_INVALIDCALL; } -static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) { - HRESULT hr; - IWineD3DSwapChain *swapchain; - - hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain); - if (SUCCEEDED(hr)) { - IWineD3DSwapChain_Release((IUnknown *)swapchain); - return swapchain; - } - - return NULL; -} - -static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, +static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface, const WINED3DRECT *rect, const float color[4]) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; struct wined3d_context *context; - if (rect) IWineD3DSurface_LoadLocation(surface, SFLAG_INDRAWABLE, NULL); - IWineD3DSurface_ModifyLocation(surface, SFLAG_INDRAWABLE, TRUE); + if (rect) IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INDRAWABLE, TRUE); - if (!surface_is_offscreen(surface)) - { - TRACE("Surface %p is onscreen\n", surface); - - context = context_acquire(This, surface, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - context_bind_fbo(context, GL_FRAMEBUFFER, NULL); - context_set_draw_buffer(context, surface_get_gl_buffer(surface)); - } - else - { - TRACE("Surface %p is offscreen\n", surface); + context = context_acquire(This, surface); + context_apply_clear_state(context, This, surface, NULL); - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo); - context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, surface); - context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, NULL, FALSE); - } + ENTER_GL(); - if (rect) { - glEnable(GL_SCISSOR_TEST); - if(surface_is_offscreen(surface)) { + if (rect) + { + if (surface_is_offscreen(surface)) glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1); - } else { - glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2, + else + glScissor(rect->x1, surface->currentDesc.Height - rect->y2, rect->x2 - rect->x1, rect->y2 - rect->y1); - } checkGLcall("glScissor"); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT); - } else { + } + else + { glDisable(GL_SCISSOR_TEST); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); - - glDisable(GL_BLEND); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE)); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3)); glClearColor(color[0], color[1], color[2], color[3]); glClear(GL_COLOR_BUFFER_BIT); @@ -5439,119 +5523,11 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); } -static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) { - unsigned int r, g, b, a; - DWORD ret; - - if (destfmt == WINED3DFMT_B8G8R8A8_UNORM - || destfmt == WINED3DFMT_B8G8R8X8_UNORM - || destfmt == WINED3DFMT_B8G8R8_UNORM) - return color; - - TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt)); - - a = (color & 0xff000000) >> 24; - r = (color & 0x00ff0000) >> 16; - g = (color & 0x0000ff00) >> 8; - b = (color & 0x000000ff) >> 0; - - switch(destfmt) - { - case WINED3DFMT_B5G6R5_UNORM: - if(r == 0xff && g == 0xff && b == 0xff) return 0xffff; - r = (r * 32) / 256; - g = (g * 64) / 256; - b = (b * 32) / 256; - ret = r << 11; - ret |= g << 5; - ret |= b; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_B5G5R5X1_UNORM: - case WINED3DFMT_B5G5R5A1_UNORM: - a = (a * 2) / 256; - r = (r * 32) / 256; - g = (g * 32) / 256; - b = (b * 32) / 256; - ret = a << 15; - ret |= r << 10; - ret |= g << 5; - ret |= b << 0; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_A8_UNORM: - TRACE("Returning %08x\n", a); - return a; - - case WINED3DFMT_B4G4R4X4_UNORM: - case WINED3DFMT_B4G4R4A4_UNORM: - a = (a * 16) / 256; - r = (r * 16) / 256; - g = (g * 16) / 256; - b = (b * 16) / 256; - ret = a << 12; - ret |= r << 8; - ret |= g << 4; - ret |= b << 0; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_B2G3R3_UNORM: - r = (r * 8) / 256; - g = (g * 8) / 256; - b = (b * 4) / 256; - ret = r << 5; - ret |= g << 2; - ret |= b << 0; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_R8G8B8X8_UNORM: - case WINED3DFMT_R8G8B8A8_UNORM: - ret = a << 24; - ret |= b << 16; - ret |= g << 8; - ret |= r << 0; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_B10G10R10A2_UNORM: - a = (a * 4) / 256; - r = (r * 1024) / 256; - g = (g * 1024) / 256; - b = (b * 1024) / 256; - ret = a << 30; - ret |= r << 20; - ret |= g << 10; - ret |= b << 0; - TRACE("Returning %08x\n", ret); - return ret; - - case WINED3DFMT_R10G10B10A2_UNORM: - a = (a * 4) / 256; - r = (r * 1024) / 256; - g = (g * 1024) / 256; - b = (b * 1024) / 256; - ret = a << 30; - ret |= b << 20; - ret |= g << 10; - ret |= r << 0; - TRACE("Returning %08x\n", ret); - return ret; - - default: - FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt)); - return 0; - } -} - static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, const WINED3DRECT *pRect, WINED3DCOLOR color) { @@ -5567,13 +5543,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { const float c[4] = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)}; - color_fill_fbo(iface, pSurface, pRect, c); + color_fill_fbo(iface, surface, pRect, c); return WINED3D_OK; } else { /* Just forward this to the DirectDraw blitting engine */ memset(&BltFx, 0, sizeof(BltFx)); BltFx.dwSize = sizeof(BltFx); - BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format_desc->format); + BltFx.u5.dwFillColor = color_convert_argb_to_fmt(color, surface->resource.format_desc->format); return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); } @@ -5583,7 +5559,7 @@ static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *ifac IWineD3DRendertargetView *rendertarget_view, const float color[4]) { IWineD3DResource *resource; - IWineD3DSurface *surface; + IWineD3DSurfaceImpl *surface; HRESULT hr; hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource); @@ -5600,7 +5576,7 @@ static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *ifac return; } - surface = (IWineD3DSurface *)resource; + surface = (IWineD3DSurfaceImpl *)resource; if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { @@ -5621,8 +5597,9 @@ static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *ifac /* Just forward this to the DirectDraw blitting engine */ memset(&BltFx, 0, sizeof(BltFx)); BltFx.dwSize = sizeof(BltFx); - BltFx.u5.dwFillColor = argb_to_fmt(c, ((IWineD3DSurfaceImpl *)surface)->resource.format_desc->format); - hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); + BltFx.u5.dwFillColor = color_convert_argb_to_fmt(c, surface->resource.format_desc->format); + hr = IWineD3DSurface_Blt((IWineD3DSurface *)surface, NULL, NULL, NULL, + WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); if (FAILED(hr)) { ERR("Blt failed, hr %#x\n", hr); @@ -5643,7 +5620,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface return WINED3DERR_INVALIDCALL; } - *ppRenderTarget = This->render_targets[RenderTargetIndex]; + *ppRenderTarget = (IWineD3DSurface *)This->render_targets[RenderTargetIndex]; TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget); /* Note inc ref on returned surface */ if(*ppRenderTarget != NULL) @@ -5652,110 +5629,103 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface } static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, - IWineD3DSurface *Front, IWineD3DSurface *Back) + IWineD3DSurface *front, IWineD3DSurface *back) { - IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front; - IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back; - IWineD3DSwapChainImpl *Swapchain; + IWineD3DSurfaceImpl *front_impl = (IWineD3DSurfaceImpl *)front; + IWineD3DSurfaceImpl *back_impl = (IWineD3DSurfaceImpl *)back; + IWineD3DSwapChainImpl *swapchain; HRESULT hr; - TRACE("iface %p, front %p, back %p.\n", iface, Front, Back); + TRACE("iface %p, front %p, back %p.\n", iface, front, back); - hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain); - if(hr != WINED3D_OK) { - ERR("Can't get the swapchain\n"); + if (FAILED(hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&swapchain))) + { + ERR("Failed to get the swapchain, hr %#x.\n", hr); return hr; } - /* Make sure to release the swapchain */ - IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain); - - if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) { - ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n"); - return WINED3DERR_INVALIDCALL; - } - else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) { - ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n"); + if (front_impl && !(front_impl->resource.usage & WINED3DUSAGE_RENDERTARGET)) + { + ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n"); + IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain); return WINED3DERR_INVALIDCALL; } - if(Swapchain->frontBuffer != Front) { - TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front); - - if(Swapchain->frontBuffer) + if (back_impl) + { + if (!(back_impl->resource.usage & WINED3DUSAGE_RENDERTARGET)) { - IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL); - ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags &= ~SFLAG_SWAPCHAIN; + ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n"); + IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain); + return WINED3DERR_INVALIDCALL; } - Swapchain->frontBuffer = Front; - if(Swapchain->frontBuffer) { - IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain); - ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN; + if (!swapchain->back_buffers) + { + swapchain->back_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*swapchain->back_buffers)); + if (!swapchain->back_buffers) + { + ERR("Failed to allocate back buffer array memory.\n"); + IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain); + return E_OUTOFMEMORY; + } } } - if(Back && !Swapchain->backBuffer) { - /* We need memory for the back buffer array - only one back buffer this way */ - Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *)); - if(!Swapchain->backBuffer) { - ERR("Out of memory\n"); - return E_OUTOFMEMORY; + if (swapchain->front_buffer != front_impl) + { + TRACE("Changing the front buffer from %p to %p.\n", swapchain->front_buffer, front_impl); + + if (swapchain->front_buffer) + { + IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->front_buffer, NULL); + swapchain->front_buffer->Flags &= ~SFLAG_SWAPCHAIN; } - } + swapchain->front_buffer = front_impl; - if(Swapchain->backBuffer[0] != Back) { - TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back); + if (front) + { + IWineD3DSurface_SetContainer(front, (IWineD3DBase *)swapchain); + front_impl->Flags |= SFLAG_SWAPCHAIN; + } + } - /* What to do about the context here in the case of multithreading? Not sure. - * This function is called by IDirect3D7::CreateDevice so in theory its initialization code - */ - WARN("No active context?\n"); + if (swapchain->back_buffers[0] != back_impl) + { + TRACE("Changing the back buffer from %p to %p.\n", swapchain->back_buffers[0], back_impl); - ENTER_GL(); - if(!Swapchain->backBuffer[0]) { - /* GL was told to draw to the front buffer at creation, - * undo that - */ - glDrawBuffer(GL_BACK); - checkGLcall("glDrawBuffer(GL_BACK)"); - /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */ - Swapchain->presentParms.BackBufferCount = 1; - } else if (!Back) { - /* That makes problems - disable for now */ - /* glDrawBuffer(GL_FRONT); */ - checkGLcall("glDrawBuffer(GL_FRONT)"); - /* We have lost our back buffer, set this to 0 to avoid confusing other code */ - Swapchain->presentParms.BackBufferCount = 0; + if (swapchain->back_buffers[0]) + { + IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->back_buffers[0], NULL); + swapchain->back_buffers[0]->Flags &= ~SFLAG_SWAPCHAIN; } - LEAVE_GL(); + swapchain->back_buffers[0] = back_impl; - if(Swapchain->backBuffer[0]) + if (back) { - IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL); - ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags &= ~SFLAG_SWAPCHAIN; + swapchain->presentParms.BackBufferWidth = back_impl->currentDesc.Width; + swapchain->presentParms.BackBufferHeight = back_impl->currentDesc.Height; + swapchain->presentParms.BackBufferFormat = back_impl->resource.format_desc->format; + swapchain->presentParms.BackBufferCount = 1; + + IWineD3DSurface_SetContainer(back, (IWineD3DBase *)swapchain); + back_impl->Flags |= SFLAG_SWAPCHAIN; } - Swapchain->backBuffer[0] = Back; - - if(Swapchain->backBuffer[0]) { - IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain); - ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags |= SFLAG_SWAPCHAIN; - Swapchain->presentParms.BackBufferWidth = BackImpl->currentDesc.Width; - Swapchain->presentParms.BackBufferHeight = BackImpl->currentDesc.Height; - Swapchain->presentParms.BackBufferFormat = BackImpl->resource.format_desc->format; - } else { - HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer); - Swapchain->backBuffer = NULL; + else + { + swapchain->presentParms.BackBufferCount = 0; + HeapFree(GetProcessHeap(), 0, swapchain->back_buffers); + swapchain->back_buffers = NULL; } - } + IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain); return WINED3D_OK; } static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - *ppZStencilSurface = This->stencilBufferTarget; + *ppZStencilSurface = (IWineD3DSurface *)This->depth_stencil; TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface); if(*ppZStencilSurface != NULL) { @@ -5767,21 +5737,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice } } -void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect, - IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) +void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect_in, + IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, const WINED3DTEXTUREFILTERTYPE filter) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */ - IWineD3DSwapChain *src_swapchain, *dst_swapchain; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; GLenum gl_filter; - POINT offset = {0, 0}; + RECT src_rect, dst_rect; - TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n", - This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip); - TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2); - TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2); + TRACE("device %p, src_surface %p, src_rect_in %s, dst_surface %p, dst_rect_in %s, filter %s (0x%08x).\n", + device, src_surface, wine_dbgstr_rect(src_rect_in), dst_surface, + wine_dbgstr_rect(dst_rect_in), debug_d3dtexturefiltertype(filter), filter); + + src_rect = *src_rect_in; + dst_rect = *dst_rect_in; switch (filter) { case WINED3DTEXF_LINEAR: @@ -5799,16 +5769,19 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED /* Make sure the drawables are up-to-date. Note that loading the * destination surface isn't strictly required if we overwrite the * entire surface. */ - IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL); - IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_LoadLocation((IWineD3DSurface *)src_surface, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_LoadLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, NULL); - /* Attach src surface to src fbo */ - src_swapchain = get_swapchain(src_surface); - dst_swapchain = get_swapchain(dst_surface); + if (!surface_is_offscreen(src_surface)) context = context_acquire(device, src_surface); + else if (!surface_is_offscreen(dst_surface)) context = context_acquire(device, dst_surface); + else context = context_acquire(device, NULL); - if (src_swapchain) context = context_acquire(This, src_surface, CTXUSAGE_RESOURCELOAD); - else if (dst_swapchain) context = context_acquire(This, dst_surface, CTXUSAGE_RESOURCELOAD); - else context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping blit.\n"); + return; + } gl_info = context->gl_info; @@ -5818,19 +5791,11 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED TRACE("Source surface %p is onscreen\n", src_surface); - if(buffer == GL_FRONT) { - RECT windowsize; - UINT h; - ClientToScreen(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &offset); - GetClientRect(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &windowsize); - h = windowsize.bottom - windowsize.top; - src_rect->x1 -= offset.x; src_rect->x2 -=offset.x; - src_rect->y1 = offset.y + h - src_rect->y1; - src_rect->y2 = offset.y + h - src_rect->y2; - } else { - src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1; - src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2; - } + if (buffer == GL_FRONT) + surface_translate_frontbuffer_coords(src_surface, context->win_handle, &src_rect); + + src_rect.top = src_surface->currentDesc.Height - src_rect.top; + src_rect.bottom = src_surface->currentDesc.Height - src_rect.bottom; ENTER_GL(); context_bind_fbo(context, GL_READ_FRAMEBUFFER, NULL); @@ -5839,11 +5804,9 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED } else { TRACE("Source surface %p is offscreen\n", src_surface); ENTER_GL(); - context_bind_fbo(context, GL_READ_FRAMEBUFFER, &context->src_fbo); - context_attach_surface_fbo(context, GL_READ_FRAMEBUFFER, 0, src_surface); + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL); glReadBuffer(GL_COLOR_ATTACHMENT0); checkGLcall("glReadBuffer()"); - context_attach_depth_stencil_fbo(context, GL_READ_FRAMEBUFFER, NULL, FALSE); } LEAVE_GL(); @@ -5854,20 +5817,11 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED TRACE("Destination surface %p is onscreen\n", dst_surface); - if(buffer == GL_FRONT) { - RECT windowsize; - UINT h; - ClientToScreen(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &offset); - GetClientRect(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &windowsize); - h = windowsize.bottom - windowsize.top; - dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x; - dst_rect->y1 = offset.y + h - dst_rect->y1; - dst_rect->y2 = offset.y + h - dst_rect->y2; - } else { - /* Screen coords = window coords, surface height = window height */ - dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1; - dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2; - } + if (buffer == GL_FRONT) + surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect); + + dst_rect.top = dst_surface->currentDesc.Height - dst_rect.top; + dst_rect.bottom = dst_surface->currentDesc.Height - dst_rect.bottom; ENTER_GL(); context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL); @@ -5878,31 +5832,23 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED TRACE("Destination surface %p is offscreen\n", dst_surface); ENTER_GL(); - context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, &context->dst_fbo); - context_attach_surface_fbo(context, GL_DRAW_FRAMEBUFFER, 0, dst_surface); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL); context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0); - context_attach_depth_stencil_fbo(context, GL_DRAW_FRAMEBUFFER, NULL, FALSE); } glDisable(GL_SCISSOR_TEST); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); + IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); - if (flip) { - gl_info->fbo_ops.glBlitFramebuffer(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2, - dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter); - checkGLcall("glBlitFramebuffer()"); - } else { - gl_info->fbo_ops.glBlitFramebuffer(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2, - dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter); - checkGLcall("glBlitFramebuffer()"); - } + gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, + dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, mask, gl_filter); + checkGLcall("glBlitFramebuffer()"); LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); - IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, TRUE); } static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget, @@ -5932,13 +5878,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, } /* If we are trying to set what we already have, don't bother */ - if (pRenderTarget == This->render_targets[RenderTargetIndex]) { + if (pRenderTarget == (IWineD3DSurface *)This->render_targets[RenderTargetIndex]) + { TRACE("Trying to do a NOP SetRenderTarget operation\n"); return WINED3D_OK; } - if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget); - if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]); - This->render_targets[RenderTargetIndex] = pRenderTarget; + if (pRenderTarget) + IWineD3DSurface_AddRef(pRenderTarget); + if (This->render_targets[RenderTargetIndex]) + IWineD3DSurface_Release((IWineD3DSurface *)This->render_targets[RenderTargetIndex]); + This->render_targets[RenderTargetIndex] = (IWineD3DSurfaceImpl *)pRenderTarget; /* Render target 0 is special */ if(RenderTargetIndex == 0 && set_viewport) { @@ -5946,8 +5895,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, * Tests show that stateblock recording is ignored, the change goes * directly into the primary stateblock. */ - This->stateBlock->viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height; - This->stateBlock->viewport.Width = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width; + This->stateBlock->viewport.Height = This->render_targets[0]->currentDesc.Height; + This->stateBlock->viewport.Width = This->render_targets[0]->currentDesc.Width; This->stateBlock->viewport.X = 0; This->stateBlock->viewport.Y = 0; This->stateBlock->viewport.MaxZ = 1.0f; @@ -5965,49 +5914,46 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - HRESULT hr = WINED3D_OK; - IWineD3DSurface *tmp; + IWineD3DSurfaceImpl *tmp; - TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil); + TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This, pNewZStencil, This->depth_stencil); - if (pNewZStencil == This->stencilBufferTarget) { - TRACE("Trying to do a NOP SetRenderTarget operation\n"); - } else { - /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead - * depending on the renter target implementation being used. - * A shared context implementation will share all buffers between all rendertargets (including swapchains), - * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the - * stencil buffer and incur an extra memory overhead - ******************************************************/ - - if (This->stencilBufferTarget) { - if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL - || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) { - surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED); - } else { - struct wined3d_context *context = context_acquire(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); - surface_load_ds_location(This->stencilBufferTarget, context, SFLAG_DS_OFFSCREEN); - surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); - context_release(context); + if (This->depth_stencil == (IWineD3DSurfaceImpl *)pNewZStencil) + { + TRACE("Trying to do a NOP SetRenderTarget operation.\n"); + return WINED3D_OK; + } + + if (This->depth_stencil) + { + if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL + || This->depth_stencil->Flags & SFLAG_DISCARD) + { + surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED, + This->depth_stencil->currentDesc.Width, + This->depth_stencil->currentDesc.Height); + if (This->depth_stencil == This->onscreen_depth_stencil) + { + IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil); + This->onscreen_depth_stencil = NULL; } } + } - tmp = This->stencilBufferTarget; - This->stencilBufferTarget = pNewZStencil; - /* should we be calling the parent or the wined3d surface? */ - if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget); - if (NULL != tmp) IWineD3DSurface_Release(tmp); - hr = WINED3D_OK; + tmp = This->depth_stencil; + This->depth_stencil = (IWineD3DSurfaceImpl *)pNewZStencil; + if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil); + if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp); - if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) { - /* Swapping NULL / non NULL depth stencil affects the depth and tests */ - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE)); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE)); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK)); - } + if ((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) + { + /* Swapping NULL / non NULL depth stencil affects the depth and tests */ + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK)); } - return hr; + return WINED3D_OK; } static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot, @@ -6020,8 +5966,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot); /* some basic validation checks */ - if(This->cursorTexture) { - struct wined3d_context *context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + if (This->cursorTexture) + { + struct wined3d_context *context = context_acquire(This, NULL); ENTER_GL(); glDeleteTextures(1, &This->cursorTexture); LEAVE_GL(); @@ -6065,15 +6012,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY))) { const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; - const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info); struct wined3d_context *context; char *mem, *bits = rect.pBits; - GLint intfmt = glDesc->glInternal; - GLint format = glDesc->glFormat; - GLint type = glDesc->glType; + GLint intfmt = format_desc->glInternal; + GLint format = format_desc->glFormat; + GLint type = format_desc->glType; INT height = This->cursorHeight; INT width = This->cursorWidth; - INT bpp = glDesc->byte_count; + INT bpp = format_desc->byte_count; DWORD sampler; INT i; @@ -6084,7 +6031,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp); IWineD3DSurface_UnlockRect(pCursorBitmap); - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); ENTER_GL(); @@ -6258,14 +6205,10 @@ static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRES while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1; while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1; } - surface->glRect.left = 0; - surface->glRect.top = 0; - surface->glRect.right = surface->pow2Width; - surface->glRect.bottom = surface->pow2Height; if (surface->texture_name) { - struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(device, NULL); ENTER_GL(); glDeleteTextures(1, &surface->texture_name); LEAVE_GL(); @@ -6286,7 +6229,7 @@ static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRES /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered * to a FBO */ - if(!surface_init_sysmem((IWineD3DSurface *) surface)) + if (!surface_init_sysmem(surface)) { return E_OUTOFMEMORY; } @@ -6327,14 +6270,14 @@ static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRE return FALSE; } -void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) { +static void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; IWineD3DBaseShaderImpl *shader; - context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL); gl_info = context->gl_info; IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL); @@ -6371,9 +6314,9 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_ swapchain->num_contexts = 0; } -HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) { +static HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface; struct wined3d_context *context; HRESULT hr; IWineD3DSurfaceImpl *target; @@ -6386,9 +6329,8 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain * return E_OUTOFMEMORY; } - target = (IWineD3DSurfaceImpl *)(swapchain->backBuffer ? swapchain->backBuffer[0] : swapchain->frontBuffer); - context = context_create(This, target, swapchain->win_handle, FALSE, &swapchain->presentParms); - if (!context) + target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer; + if (!(context = context_create(swapchain, target, swapchain->ds_format))) { WARN("Failed to create context.\n"); HeapFree(GetProcessHeap(), 0, swapchain->context); @@ -6427,7 +6369,7 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain * return WINED3D_OK; err: - context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); + context_acquire(This, NULL); destroy_dummy_textures(This, context->gl_info); context_release(context); context_destroy(This, context); @@ -6499,7 +6441,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) { ERR("Cannot change the device window yet\n"); } - if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil_buffer) { + if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil) + { HRESULT hrc; TRACE("Creating the depth stencil buffer\n"); @@ -6512,7 +6455,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE pPresentationParameters->MultiSampleType, pPresentationParameters->MultiSampleQuality, FALSE, - &This->auto_depth_stencil_buffer); + (IWineD3DSurface **)&This->auto_depth_stencil); if (FAILED(hrc)) { ERR("Failed to create the depth stencil buffer\n"); @@ -6521,9 +6464,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE } } + if (This->onscreen_depth_stencil) + { + IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil); + This->onscreen_depth_stencil = NULL; + } + /* Reset the depth stencil */ if (pPresentationParameters->EnableAutoDepthStencil) - IWineD3DDevice_SetDepthStencilSurface(iface, This->auto_depth_stencil_buffer); + IWineD3DDevice_SetDepthStencilSurface(iface, (IWineD3DSurface *)This->auto_depth_stencil); else IWineD3DDevice_SetDepthStencilSurface(iface, NULL); @@ -6531,7 +6480,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock); IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock); - delete_opengl_contexts(iface, (IWineD3DSwapChain *) swapchain); + delete_opengl_contexts(iface, swapchain); if(pPresentationParameters->Windowed) { mode.Width = swapchain->orig_width; @@ -6558,23 +6507,25 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth; swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight; - hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters); + hr = updateSurfaceDesc(swapchain->front_buffer, pPresentationParameters); if(FAILED(hr)) { IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return hr; } - for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) { - hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters); + for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i) + { + hr = updateSurfaceDesc(swapchain->back_buffers[i], pPresentationParameters); if(FAILED(hr)) { IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return hr; } } - if(This->auto_depth_stencil_buffer) { - hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); + if (This->auto_depth_stencil) + { + hr = updateSurfaceDesc(This->auto_depth_stencil, pPresentationParameters); if(FAILED(hr)) { IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); @@ -6583,24 +6534,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE } } - if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) || - (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) || - DisplayModeChanged) { - + if (!pPresentationParameters->Windowed != !swapchain->presentParms.Windowed + || DisplayModeChanged) + { IWineD3DDevice_SetDisplayMode(iface, 0, &mode); - if(swapchain->win_handle && !pPresentationParameters->Windowed) { + if (!pPresentationParameters->Windowed) + { if(swapchain->presentParms.Windowed) { /* switch from windowed to fs */ swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight); } else { /* Fullscreen -> fullscreen mode change */ - MoveWindow(swapchain->win_handle, 0, 0, + MoveWindow(swapchain->device_window, 0, 0, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, TRUE); } - } else if(swapchain->win_handle && !swapchain->presentParms.Windowed) { + } + else if (!swapchain->presentParms.Windowed) + { /* Fullscreen -> windowed switch */ swapchain_restore_fullscreen_window(swapchain); } @@ -6657,7 +6610,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE } } - hr = create_primary_opengl_context(iface, (IWineD3DSwapChain *) swapchain); + hr = create_primary_opengl_context(iface, swapchain); IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); /* All done. There is no need to reload resources or shaders, this will happen automatically on the @@ -6747,13 +6700,11 @@ void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resour { for (i = 0; i < This->adapter->gl_info.limits.buffers; ++i) { - if (This->render_targets[i] == (IWineD3DSurface *)resource) { + if (This->render_targets[i] == (IWineD3DSurfaceImpl *)resource) This->render_targets[i] = NULL; - } - } - if (This->stencilBufferTarget == (IWineD3DSurface *)resource) { - This->stencilBufferTarget = NULL; } + if (This->depth_stencil == (IWineD3DSurfaceImpl *)resource) + This->depth_stencil = NULL; } break; @@ -6845,6 +6796,28 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3 return WINED3D_OK; } +static HRESULT WINAPI IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice *iface, HDC dc, IWineD3DSurface **surface) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DResourceImpl *resource; + + LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) + { + WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource); + if (type == WINED3DRTYPE_SURFACE) + { + if (((IWineD3DSurfaceImpl *)resource)->hDC == dc) + { + TRACE("Found surface %p for dc %p.\n", resource, dc); + *surface = (IWineD3DSurface *)resource; + return WINED3D_OK; + } + } + } + + return WINED3DERR_INVALIDCALL; +} + /********************************************************** * IWineD3DDevice VTbl follows **********************************************************/ @@ -6993,7 +6966,10 @@ static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_UpdateSurface, IWineD3DDeviceImpl_GetFrontBufferData, /*** object tracking ***/ - IWineD3DDeviceImpl_EnumResources + IWineD3DDeviceImpl_EnumResources, + IWineD3DDeviceImpl_GetSurfaceFromDC, + IWineD3DDeviceImpl_AcquireFocusWindow, + IWineD3DDeviceImpl_ReleaseFocusWindow, }; HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d, @@ -7045,27 +7021,29 @@ HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d, select_shader_mode(&adapter->gl_info, &device->ps_selected_mode, &device->vs_selected_mode); device->shader_backend = adapter->shader_backend; - memset(&shader_caps, 0, sizeof(shader_caps)); - device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps); - device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst; - device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst; - device->vs_clipping = shader_caps.VSClipping; - - memset(&ffp_caps, 0, sizeof(ffp_caps)); + if (device->shader_backend) + { + device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps); + device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst; + device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst; + device->vs_clipping = shader_caps.VSClipping; + } fragment_pipeline = adapter->fragment_pipe; device->frag_pipe = fragment_pipeline; - fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps); - device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures; - - hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info, - ffp_vertexstate_template, fragment_pipeline, misc_state_template); - if (FAILED(hr)) + if (fragment_pipeline) { - ERR("Failed to compile state table, hr %#x.\n", hr); - IWineD3D_Release(device->wined3d); - return hr; - } + fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps); + device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures; + hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info, + ffp_vertexstate_template, fragment_pipeline, misc_state_template); + if (FAILED(hr)) + { + ERR("Failed to compile state table, hr %#x.\n", hr); + IWineD3D_Release(device->wined3d); + return hr; + } + } device->blitter = adapter->blitter; return WINED3D_OK; @@ -7090,31 +7068,21 @@ void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { } } -void get_drawable_size_pbuffer(struct wined3d_context *context, UINT *width, UINT *height) -{ - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.device; - /* The drawable size of a pbuffer render target is the current pbuffer size. */ - *width = device->pbufferWidth; - *height = device->pbufferHeight; -} - void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height) { - IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->current_rt; /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */ - *width = surface->pow2Width; - *height = surface->pow2Height; + *width = context->current_rt->pow2Width; + *height = context->current_rt->pow2Height; } void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) { - IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->surface; + IWineD3DSwapChainImpl *swapchain = context->swapchain; /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the * current context's drawable, which is the size of the back buffer of the swapchain - * the active context belongs to. The back buffer of the swapchain is stored as the - * surface the context belongs to. */ - *width = surface->currentDesc.Width; - *height = surface->currentDesc.Height; + * the active context belongs to. */ + *width = swapchain->presentParms.BackBufferWidth; + *height = swapchain->presentParms.BackBufferHeight; } LRESULT device_process_message(IWineD3DDeviceImpl *device, HWND window, diff --git a/reactos/dll/directx/wine/wined3d/directx.c b/reactos/dll/directx/wine/wined3d/directx.c index 812e5ccc9e8..29061476ddd 100644 --- a/reactos/dll/directx/wine/wined3d/directx.c +++ b/reactos/dll/directx/wine/wined3d/directx.c @@ -24,14 +24,13 @@ */ #include "config.h" +#include #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); -#define GLINFO_LOCATION (*gl_info) #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024) -#define MAKEDWORD_VERSION(maj, min) ((maj & 0xffff) << 16) | (min & 0xffff) /* The d3d device ID */ static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } }; @@ -74,6 +73,7 @@ static const struct { {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 }, {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 }, {"GL_ARB_shading_language_100", ARB_SHADING_LANGUAGE_100, 0 }, + {"GL_ARB_shadow", ARB_SHADOW, 0 }, {"GL_ARB_sync", ARB_SYNC, 0 }, {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 }, {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 }, @@ -104,6 +104,7 @@ static const struct { {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 }, {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 }, {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 }, + {"GL_EXT_draw_buffers2", EXT_DRAW_BUFFERS2, 0 }, {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 }, {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 }, {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 }, @@ -325,12 +326,12 @@ fail: } /* Adjust the amount of used texture memory */ -long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram) +unsigned int WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *device, unsigned int glram) { - struct wined3d_adapter *adapter = D3DDevice->adapter; + struct wined3d_adapter *adapter = device->adapter; adapter->UsedTextureRam += glram; - TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam); + TRACE("Adjusted gl ram by %d to %d\n", glram, adapter->UsedTextureRam); return adapter->UsedTextureRam; } @@ -528,9 +529,12 @@ static void test_pbo_functionality(struct wined3d_gl_info *gl_info) checkGLcall("Loading the PBO test texture"); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + LEAVE_GL(); + wglFinish(); /* just to be sure */ memset(check, 0, sizeof(check)); + ENTER_GL(); glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check); checkGLcall("Reading back the PBO test texture"); @@ -570,7 +574,7 @@ static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer, enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) { - return (gl_vendor == GL_VENDOR_ATI); + return gl_vendor == GL_VENDOR_FGLRX; } @@ -669,6 +673,61 @@ static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const ch return ret; } +/* Context activation is done by the caller. */ +static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + char data[4 * 4 * 4]; + GLuint tex, fbo; + GLenum status; + + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE; + + memset(data, 0xcc, sizeof(data)); + + ENTER_GL(); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + checkGLcall("glTexImage2D"); + + gl_info->fbo_ops.glGenFramebuffers(1, &fbo); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + checkGLcall("glFramebufferTexture2D"); + + status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status); + checkGLcall("glCheckFramebufferStatus"); + + memset(data, 0x11, sizeof(data)); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + checkGLcall("glTexSubImage2D"); + + glClearColor(0.996, 0.729, 0.745, 0.792); + glClear(GL_COLOR_BUFFER_BIT); + checkGLcall("glClear"); + + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + checkGLcall("glGetTexImage"); + + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + checkGLcall("glBindTexture"); + + gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo); + glDeleteTextures(1, &tex); + checkGLcall("glDeleteTextures"); + + LEAVE_GL(); + + return *(DWORD *)data == 0x11111111; +} + static void quirk_arb_constants(struct wined3d_gl_info *gl_info) { TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants); @@ -797,6 +856,11 @@ static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info) gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN; } +static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE; +} + struct driver_quirk { BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, @@ -876,6 +940,11 @@ static const struct driver_quirk quirk_table[] = quirk_disable_nvvp_clip, "Apple NV_vertex_program clip bug quirk" }, + { + match_fbo_tex_update, + quirk_fbo_tex_update, + "FBO rebind for attachment updates" + }, }; /* Certain applications (Steam) complain if we report an outdated driver version. In general, @@ -955,7 +1024,7 @@ static const struct driver_version_information driver_version_table[] = {HW_VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 }, {HW_VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 }, {HW_VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 }, - {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 14, 10, 6764 }, + {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2350, "ATI Mobility Radeon HD 2350", 14, 10, 6764 }, {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 }, {HW_VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 }, {HW_VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 }, @@ -1131,10 +1200,11 @@ static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl return GL_VENDOR_NVIDIA; if (strstr(gl_vendor_string, "ATI")) - return GL_VENDOR_ATI; + return GL_VENDOR_FGLRX; if (strstr(gl_vendor_string, "Intel(R)") - || strstr(gl_renderer, "Intel(R)") + /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */ + || strstr(gl_renderer, "Intel") || strstr(gl_vendor_string, "Intel Inc.")) return GL_VENDOR_INTEL; @@ -1148,9 +1218,10 @@ static enum wined3d_gl_vendor wined3d_guess_gl_vendor(struct wined3d_gl_info *gl || strstr(gl_renderer, "Gallium")) return GL_VENDOR_MESA; - FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_WINE.\n", debugstr_a(gl_vendor_string)); + FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n", + debugstr_a(gl_vendor_string)); - return GL_VENDOR_WINE; + return GL_VENDOR_UNKNOWN; } static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer) @@ -1165,14 +1236,15 @@ static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_s return HW_VENDOR_ATI; if (strstr(gl_vendor_string, "Intel(R)") - || strstr(gl_renderer, "Intel(R)") + /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */ + || strstr(gl_renderer, "Intel") || strstr(gl_vendor_string, "Intel Inc.")) return HW_VENDOR_INTEL; if (strstr(gl_vendor_string, "Mesa") || strstr(gl_vendor_string, "Tungsten Graphics, Inc") || strstr(gl_vendor_string, "VMware, Inc.")) - return HW_VENDOR_WINE; + return HW_VENDOR_SOFTWARE; FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string)); @@ -1181,13 +1253,10 @@ static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_s -enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { - /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more - * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. - */ - if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3]) + if (WINE_D3D10_CAPABLE(gl_info)) { /* Geforce 200 - highend */ if (strstr(gl_renderer, "GTX 280") @@ -1293,6 +1362,16 @@ enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info * return CARD_NVIDIA_GEFORCE_8300GS; } + /* Geforce8-compatible fall back if the GPU is not in the list yet */ + *vidmem = 128; + return CARD_NVIDIA_GEFORCE_8300GS; + } + + /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more + * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. + */ + if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3]) + { /* Geforce7 - highend */ if (strstr(gl_renderer, "7800") || strstr(gl_renderer, "7900") @@ -1425,14 +1504,14 @@ enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info * } -enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx * * Beware: renderer string do not match exact card model, * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */ - if (WINE_D3D9_CAPABLE(gl_info)) + if (WINE_D3D10_CAPABLE(gl_info)) { /* Radeon EG CYPRESS XT / PRO HD5800 - highend */ if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */ @@ -1507,16 +1586,17 @@ enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_ return CARD_ATI_RADEON_HD2600; } - /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */ - if (strstr(gl_renderer, "HD 2300") + /* Radeon R6xx HD2350/HD2400/HD3400 - lowend + * Note HD2300=DX9, HD2350=DX10 */ + if (strstr(gl_renderer, "HD 2350") || strstr(gl_renderer, "HD 2400") || strstr(gl_renderer, "HD 3470") || strstr(gl_renderer, "HD 3450") || strstr(gl_renderer, "HD 3430") || strstr(gl_renderer, "HD 3400")) { - *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ - return CARD_ATI_RADEON_HD2300; + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; } /* Radeon R6xx/R7xx integrated */ @@ -1528,6 +1608,13 @@ enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_ return CARD_ATI_RADEON_HD3200; } + /* Default for when no GPU has been found */ + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { /* Radeon R5xx */ if (strstr(gl_renderer, "X1600") || strstr(gl_renderer, "X1650") @@ -1539,14 +1626,19 @@ enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_ return CARD_ATI_RADEON_X1600; } - /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */ + /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx) + * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */ if (strstr(gl_renderer, "X700") || strstr(gl_renderer, "X800") || strstr(gl_renderer, "X850") || strstr(gl_renderer, "X1300") || strstr(gl_renderer, "X1400") || strstr(gl_renderer, "X1450") - || strstr(gl_renderer, "X1550")) + || strstr(gl_renderer, "X1550") + || strstr(gl_renderer, "X2300") + || strstr(gl_renderer, "X2500") + || strstr(gl_renderer, "HD 2300") + ) { *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */ return CARD_ATI_RADEON_X700; @@ -1581,8 +1673,8 @@ enum wined3d_pci_device select_card_ati_binary(const struct wined3d_gl_info *gl_ } -enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { if (strstr(gl_renderer, "X3100")) { @@ -1607,8 +1699,8 @@ enum wined3d_pci_device select_card_intel_binary(const struct wined3d_gl_info *g } -enum wined3d_pci_device (select_card_ati_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_ati_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx * @@ -1663,12 +1755,12 @@ enum wined3d_pci_device (select_card_ati_mesa)(const struct wined3d_gl_info *gl_ return CARD_ATI_RADEON_HD2600; } - /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */ + /* Radeon R6xx HD2350/HD2400/HD3400 - lowend */ if (strstr(gl_renderer, "RV610") || strstr(gl_renderer, "RV620")) { - *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ - return CARD_ATI_RADEON_HD2300; + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; } /* Radeon R6xx/R7xx integrated */ @@ -1786,8 +1878,8 @@ enum wined3d_pci_device (select_card_ati_mesa)(const struct wined3d_gl_info *gl_ if (strstr(gl_renderer, "(RV610") || strstr(gl_renderer, "(RV620")) { - *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ - return CARD_ATI_RADEON_HD2300; + *vidmem = 256; /* HD2350/2400 use 256MB, HD34xx use 256-512MB */ + return CARD_ATI_RADEON_HD2350; } /* Radeon R6xx/R7xx integrated */ @@ -1816,8 +1908,8 @@ enum wined3d_pci_device (select_card_ati_mesa)(const struct wined3d_gl_info *gl_ } -enum wined3d_pci_device (select_card_nvidia_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { FIXME_(d3d_caps)("Card selection not handled for Mesa Nouveau driver\n"); if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600; @@ -1827,8 +1919,8 @@ enum wined3d_pci_device (select_card_nvidia_mesa)(const struct wined3d_gl_info * return CARD_NVIDIA_RIVA_128; } -enum wined3d_pci_device (select_card_intel_mesa)(const struct wined3d_gl_info *gl_info, const char *gl_renderer, - unsigned int *vidmem ) +static enum wined3d_pci_device select_card_intel_mesa(const struct wined3d_gl_info *gl_info, + const char *gl_renderer, unsigned int *vidmem) { FIXME_(d3d_caps)("Card selection not handled for Mesa Intel driver\n"); return CARD_INTEL_I915G; @@ -1850,10 +1942,11 @@ static const struct vendor_card_selection vendor_card_select_table[] = {GL_VENDOR_APPLE, HW_VENDOR_NVIDIA, "Apple OSX NVidia binary driver", select_card_nvidia_binary}, {GL_VENDOR_APPLE, HW_VENDOR_ATI, "Apple OSX AMD/ATI binary driver", select_card_ati_binary}, {GL_VENDOR_APPLE, HW_VENDOR_INTEL, "Apple OSX Intel binary driver", select_card_intel_binary}, - {GL_VENDOR_ATI, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary}, + {GL_VENDOR_FGLRX, HW_VENDOR_ATI, "AMD/ATI binary driver", select_card_ati_binary}, {GL_VENDOR_MESA, HW_VENDOR_ATI, "Mesa AMD/ATI driver", select_card_ati_mesa}, {GL_VENDOR_MESA, HW_VENDOR_NVIDIA, "Mesa Nouveau driver", select_card_nvidia_mesa}, - {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa} + {GL_VENDOR_MESA, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa}, + {GL_VENDOR_INTEL, HW_VENDOR_INTEL, "Mesa Intel driver", select_card_intel_mesa} }; @@ -2034,6 +2127,7 @@ static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter) * with Default values */ memset(gl_info->supported, 0, sizeof(gl_info->supported)); + gl_info->limits.blends = 1; gl_info->limits.buffers = 1; gl_info->limits.textures = 1; gl_info->limits.fragment_samplers = 1; @@ -2347,7 +2441,13 @@ static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter) if (gl_info->supported[ARB_SHADING_LANGUAGE_100]) { const char *str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); + unsigned int major, minor; + TRACE_(d3d_caps)("GLSL version string: %s.\n", debugstr_a(str)); + + /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */ + sscanf(str, "%u.%u", &major, &minor); + gl_info->glsl_version = MAKEDWORD_VERSION(major, minor); } if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) { @@ -2522,10 +2622,6 @@ static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_adapter *adapter) ThisExtn[len] = '\0'; TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn)); - if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) { - gl_info->supported[WGL_ARB_PBUFFER] = TRUE; - TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n"); - } if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) { gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE; TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n"); @@ -2590,7 +2686,7 @@ static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Ad /* TODO: Store modes per adapter and read it from the adapter structure */ if (Adapter == 0) { /* Display */ - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info); UINT format_bits = format_desc->byte_count * CHAR_BIT; unsigned int i = 0; unsigned int j = 0; @@ -2637,7 +2733,7 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte /* TODO: Store modes per adapter and read it from the adapter structure */ if (Adapter == 0) { - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info); UINT format_bits = format_desc->byte_count * CHAR_BIT; DEVMODEW DevModeW; int ModeIdx = 0; @@ -2802,13 +2898,16 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad } static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info, - const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc) + const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc) { short redSize, greenSize, blueSize, alphaSize, colorBits; if(!cfg) return FALSE; + /* Float formats need FBOs. If FBOs are used this function isn't called */ + if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE; + if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */ if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) { @@ -2829,29 +2928,14 @@ static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined return FALSE; return TRUE; - } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */ - if (format_desc->format == WINED3DFMT_R16_FLOAT) - return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0); - if (format_desc->format == WINED3DFMT_R16G16_FLOAT) - return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0); - if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT) - return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16); - if (format_desc->format == WINED3DFMT_R32_FLOAT) - return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0); - if (format_desc->format == WINED3DFMT_R32G32_FLOAT) - return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0); - if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT) - return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32); - } else { - /* Probably a color index mode */ - return FALSE; } + /* Probably a RGBA_float or color index mode */ return FALSE; } static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info, - const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc) + const WineD3D_PixelFormat *cfg, const struct wined3d_format_desc *format_desc) { short depthSize, stencilSize; BOOL lockable = FALSE; @@ -2865,6 +2949,9 @@ static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3 return FALSE; } + /* Float formats need FBOs. If FBOs are used this function isn't called */ + if (format_desc->Flags & WINED3DFMT_FLAG_FLOAT) return FALSE; + if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT)) lockable = TRUE; @@ -2890,8 +2977,8 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT int nCfgs; const WineD3D_PixelFormat *cfgs; const struct wined3d_adapter *adapter; - const struct GlPixelFormatDesc *rt_format_desc; - const struct GlPixelFormatDesc *ds_format_desc; + const struct wined3d_format_desc *rt_format_desc; + const struct wined3d_format_desc *ds_format_desc; int it; WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n", @@ -2909,15 +2996,26 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT adapter = &This->adapters[Adapter]; rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info); ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info); - cfgs = adapter->cfgs; - nCfgs = adapter->nCfgs; - for (it = 0; it < nCfgs; ++it) { - if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc)) - { - if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc)) + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + if ((rt_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET) && + (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) { + TRACE_(d3d_caps)("(%p) : Formats matched\n", This); + return WINED3D_OK; + } + } + else + { + cfgs = adapter->cfgs; + nCfgs = adapter->nCfgs; + for (it = 0; it < nCfgs; ++it) { + if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc)) { - TRACE_(d3d_caps)("(%p) : Formats matched\n", This); - return WINED3D_OK; + if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc)) + { + TRACE_(d3d_caps)("(%p) : Formats matched\n", This); + return WINED3D_OK; + } } } } @@ -2930,7 +3028,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels) { IWineD3DImpl *This = (IWineD3DImpl *)iface; - const struct GlPixelFormatDesc *glDesc; + const struct wined3d_format_desc *glDesc; const struct wined3d_adapter *adapter; TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n", @@ -3109,51 +3207,41 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter /* Check if we support bumpmapping for a format */ -static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter, - WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { - switch(format_desc->format) - { - case WINED3DFMT_R8G8_SNORM: - case WINED3DFMT_R16G16_SNORM: - case WINED3DFMT_R5G5_SNORM_L6_UNORM: - case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: - case WINED3DFMT_R8G8B8A8_SNORM: - /* Ask the fixed function pipeline implementation if it can deal - * with the conversion. If we've got a GL extension giving native - * support this will be an identity conversion. */ - if (adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup)) - { - TRACE_(d3d_caps)("[OK]\n"); - return TRUE; - } - TRACE_(d3d_caps)("[FAILED]\n"); - return FALSE; - - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return FALSE; - } + /* Ask the fixed function pipeline implementation if it can deal + * with the conversion. If we've got a GL extension giving native + * support this will be an identity conversion. */ + return (format_desc->Flags & WINED3DFMT_FLAG_BUMPMAP) + && adapter->fragment_pipe->color_fixup_supported(format_desc->color_fixup); } /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */ static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter, - const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc) + const struct wined3d_format_desc *display_format_desc, const struct wined3d_format_desc *ds_format_desc) { int it=0; /* Only allow depth/stencil formats */ if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE; - /* Walk through all WGL pixel formats to find a match */ - for (it = 0; it < adapter->nCfgs; ++it) + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - WineD3D_PixelFormat *cfg = &adapter->cfgs[it]; - if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc)) + /* With FBOs WGL limitations do not apply, but the format needs to be FBO attachable */ + if (ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) return TRUE; + } + else + { + /* Walk through all WGL pixel formats to find a match */ + for (it = 0; it < adapter->nCfgs; ++it) { - if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc)) + WineD3D_PixelFormat *cfg = &adapter->cfgs[it]; + if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc)) { - return TRUE; + if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc)) + { + return TRUE; + } } } } @@ -3161,7 +3249,7 @@ static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter, return FALSE; } -static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { /* The flags entry of a format contains the filtering capability */ if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE; @@ -3171,11 +3259,10 @@ static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct /* Check the render target capabilities of a format */ static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter, - const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc) + const struct wined3d_format_desc *adapter_format_desc, const struct wined3d_format_desc *check_format_desc) { /* Filter out non-RT formats */ if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE; - if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) { WineD3D_PixelFormat *cfgs = adapter->cfgs; int it; @@ -3204,23 +3291,9 @@ static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter, return TRUE; } } - } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) { - /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */ - WineD3D_PixelFormat *cfgs = adapter->cfgs; - int it; - - /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */ - for (it = 0; it < adapter->nCfgs; ++it) - { - if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, - &cfgs[it], check_format_desc)) - { - TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", - cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format)); - return TRUE; - } - } - } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){ + } + else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { /* For now return TRUE for FBOs until we have some proper checks. * Note that this function will only be called when the format is around for texturing. */ return TRUE; @@ -3228,46 +3301,18 @@ static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter, return FALSE; } -static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { - const struct wined3d_gl_info *gl_info = &adapter->gl_info; - - /* Check for supported sRGB formats (Texture loading and framebuffer) */ - if (!gl_info->supported[EXT_TEXTURE_SRGB]) - { - TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n"); - return FALSE; - } - - switch (format_desc->format) - { - case WINED3DFMT_B8G8R8A8_UNORM: - case WINED3DFMT_B8G8R8X8_UNORM: - case WINED3DFMT_B4G4R4A4_UNORM: - case WINED3DFMT_L8_UNORM: - case WINED3DFMT_L8A8_UNORM: - case WINED3DFMT_DXT1: - case WINED3DFMT_DXT2: - case WINED3DFMT_DXT3: - case WINED3DFMT_DXT4: - case WINED3DFMT_DXT5: - TRACE_(d3d_caps)("[OK]\n"); - return TRUE; - - default: - TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format)); - return FALSE; - } - return FALSE; + return adapter->gl_info.supported[EXT_TEXTURE_SRGB] + && (format_desc->Flags & WINED3DFMT_FLAG_SRGB_READ); } -static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter, - WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are * doing the color fixup in shaders. * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */ - if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM)) + if (format_desc->Flags & WINED3DFMT_FLAG_SRGB_WRITE) { int vs_selected_mode; int ps_selected_mode; @@ -3285,7 +3330,7 @@ static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter, /* Check if a format support blending in combination with pixel shaders */ static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter, - const struct GlPixelFormatDesc *format_desc) + const struct wined3d_format_desc *format_desc) { /* The flags entry of a format contains the post pixel shader blending capability */ if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE; @@ -3293,7 +3338,7 @@ static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapt return FALSE; } -static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported, * but we have to report mipmapping so we cannot reject this flag. Tests show that @@ -3308,8 +3353,7 @@ static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const str } /* Check if a texture format is supported on the given adapter */ -static BOOL CheckTextureCapability(struct wined3d_adapter *adapter, - WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckTextureCapability(struct wined3d_adapter *adapter, const struct wined3d_format_desc *format_desc) { const struct wined3d_gl_info *gl_info = &adapter->gl_info; @@ -3340,12 +3384,12 @@ static BOOL CheckTextureCapability(struct wined3d_adapter *adapter, return FALSE; /***** - * supported: Palettized + * Not supported: Palettized + * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of <=Direct3D7. + * Since it is not widely available, don't offer it. Further no Windows driver offers + * WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either. */ case WINED3DFMT_P8_UINT: - TRACE_(d3d_caps)("[OK]\n"); - return TRUE; - /* No Windows driver offers WINED3DFMT_P8_UINT_A8_UNORM, so don't offer it either */ case WINED3DFMT_P8_UINT_A8_UNORM: return FALSE; @@ -3539,8 +3583,10 @@ static BOOL CheckTextureCapability(struct wined3d_adapter *adapter, return FALSE; } -static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc, - WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType) +static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, + const struct wined3d_format_desc *adapter_format_desc, + const struct wined3d_format_desc *check_format_desc, + WINED3DSURFTYPE SurfaceType) { if(SurfaceType == SURFACE_GDI) { switch(check_format_desc->format) @@ -3572,12 +3618,14 @@ static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct } /* All format that are supported for textures are supported for surfaces as well */ - if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE; + if (CheckTextureCapability(adapter, check_format_desc)) return TRUE; /* All depth stencil formats are supported on surfaces */ if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE; /* If opengl can't process the format natively, the blitter may be able to convert it */ - if (adapter->blitter->color_fixup_supported(check_format_desc->color_fixup)) + if (adapter->blitter->blit_supported(&adapter->gl_info, BLIT_OP_BLIT, + NULL, WINED3DPOOL_DEFAULT, 0, check_format_desc, + NULL, WINED3DPOOL_DEFAULT, 0, adapter_format_desc)) { TRACE_(d3d_caps)("[OK]\n"); return TRUE; @@ -3588,32 +3636,11 @@ static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct return FALSE; } -static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc) +static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, + const struct wined3d_format_desc *format_desc) { - const struct wined3d_gl_info *gl_info = &adapter->gl_info; - - if (!gl_info->limits.vertex_samplers) - { - TRACE_(d3d_caps)("[FAILED]\n"); - return FALSE; - } - - switch (format_desc->format) - { - case WINED3DFMT_R32G32B32A32_FLOAT: - if (!gl_info->supported[ARB_TEXTURE_FLOAT]) - { - TRACE_(d3d_caps)("[FAILED]\n"); - return FALSE; - } - TRACE_(d3d_caps)("[OK]\n"); - return TRUE; - - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return FALSE; - } - return FALSE; + return adapter->gl_info.limits.vertex_samplers + && (format_desc->Flags & WINED3DFMT_FLAG_VTF); } static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, @@ -3623,8 +3650,8 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt IWineD3DImpl *This = (IWineD3DImpl *)iface; struct wined3d_adapter *adapter = &This->adapters[Adapter]; const struct wined3d_gl_info *gl_info = &adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info); - const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(CheckFormat, gl_info); + const struct wined3d_format_desc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info); DWORD UsageCaps = 0; TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n", @@ -3640,484 +3667,476 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_INVALIDCALL; } - if(RType == WINED3DRTYPE_CUBETEXTURE) { + switch (RType) + { + case WINED3DRTYPE_CUBETEXTURE: + /* Cubetexture allows: + * - WINED3DUSAGE_AUTOGENMIPMAP + * - WINED3DUSAGE_DEPTHSTENCIL + * - WINED3DUSAGE_DYNAMIC + * - WINED3DUSAGE_NONSECURE (d3d9ex) + * - WINED3DUSAGE_RENDERTARGET + * - WINED3DUSAGE_SOFTWAREPROCESSING + * - WINED3DUSAGE_QUERY_WRAPANDMIP + */ + if (SurfaceType != SURFACE_OPENGL) + { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } - if(SurfaceType != SURFACE_OPENGL) { - TRACE("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + { + TRACE_(d3d_caps)("[FAILED] - No cube texture support\n"); + return WINED3DERR_NOTAVAILABLE; + } - /* Cubetexture allows: - * - D3DUSAGE_AUTOGENMIPMAP - * - D3DUSAGE_DEPTHSTENCIL - * - D3DUSAGE_DYNAMIC - * - D3DUSAGE_NONSECURE (d3d9ex) - * - D3DUSAGE_RENDERTARGET - * - D3DUSAGE_SOFTWAREPROCESSING - * - D3DUSAGE_QUERY_WRAPANDMIP - */ - if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) - { - /* Check if the texture format is around */ - if (CheckTextureCapability(adapter, DeviceType, format_desc)) + if (!CheckTextureCapability(adapter, format_desc)) { - if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - /* Check for automatic mipmap generation support */ - if (gl_info->supported[SGIS_GENERATE_MIPMAP]) - { - UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP; - } else { - /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */ - TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n"); - } - } + TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n"); + return WINED3DERR_NOTAVAILABLE; + } - /* Always report dynamic locking */ - if(Usage & WINED3DUSAGE_DYNAMIC) - UsageCaps |= WINED3DUSAGE_DYNAMIC; + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + /* When autogenmipmap isn't around continue and return + * WINED3DOK_NOAUTOGEN instead of D3D_OK. */ + TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n"); + else + UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP; + } - if(Usage & WINED3DUSAGE_RENDERTARGET) { - if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) - { - UsageCaps |= WINED3DUSAGE_RENDERTARGET; - } else { - TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); - return WINED3DERR_NOTAVAILABLE; - } + /* Always report dynamic locking. */ + if (Usage & WINED3DUSAGE_DYNAMIC) + UsageCaps |= WINED3DUSAGE_DYNAMIC; + + if (Usage & WINED3DUSAGE_RENDERTARGET) + { + if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } - /* Always report software processing */ - if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) - UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; + /* Always report software processing. */ + if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; - /* Check QUERY_FILTER support */ - if(Usage & WINED3DUSAGE_QUERY_FILTER) { - if (CheckFilterCapability(adapter, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_FILTER; - } else { - TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_FILTER) + { + if (!CheckFilterCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; + } - /* Check QUERY_POSTPIXELSHADER_BLENDING support */ - if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { - if (CheckPostPixelShaderBlendingCapability(adapter, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; - } else { - TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) + { + if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; + } - /* Check QUERY_SRGBREAD support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { - if (CheckSrgbReadCapability(adapter, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; - } else { - TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) + { + if (!CheckSrgbReadCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; + } - /* Check QUERY_SRGBWRITE support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { - if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; - } else { - TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE) + { + if (!CheckSrgbWriteCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; + } - /* Check QUERY_VERTEXTEXTURE support */ - if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { - if (CheckVertexTextureCapability(adapter, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; - } else { - TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) + { + if (!CheckVertexTextureCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); + return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; + } - /* Check QUERY_WRAPANDMIP support */ - if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { - if (CheckWrapAndMipCapability(adapter, format_desc)) - { - UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; - } else { - TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) + { + if (!CheckWrapAndMipCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); + return WINED3DERR_NOTAVAILABLE; } - } else { - TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n"); + UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; + } + break; + + case WINED3DRTYPE_SURFACE: + /* Surface allows: + * - WINED3DUSAGE_DEPTHSTENCIL + * - WINED3DUSAGE_NONSECURE (d3d9ex) + * - WINED3DUSAGE_RENDERTARGET + */ + if (!CheckSurfaceCapability(adapter, adapter_format_desc, format_desc, SurfaceType)) + { + TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n"); return WINED3DERR_NOTAVAILABLE; } - } else { - TRACE_(d3d_caps)("[FAILED] - No cube texture support\n"); - return WINED3DERR_NOTAVAILABLE; - } - } else if(RType == WINED3DRTYPE_SURFACE) { - /* Surface allows: - * - D3DUSAGE_DEPTHSTENCIL - * - D3DUSAGE_NONSECURE (d3d9ex) - * - D3DUSAGE_RENDERTARGET - */ - if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType)) - { - if(Usage & WINED3DUSAGE_DEPTHSTENCIL) { - if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc)) + if (Usage & WINED3DUSAGE_DEPTHSTENCIL) + { + if (!CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc)) { - UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; - } else { TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; } - if(Usage & WINED3DUSAGE_RENDERTARGET) { - if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) + if (Usage & WINED3DUSAGE_RENDERTARGET) + { + if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) { - UsageCaps |= WINED3DUSAGE_RENDERTARGET; - } else { TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_RENDERTARGET; } - /* Check QUERY_POSTPIXELSHADER_BLENDING support */ - if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { - if (CheckPostPixelShaderBlendingCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) + { + if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; - } else { TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; } - } else { - TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n"); - return WINED3DERR_NOTAVAILABLE; - } + break; - } else if(RType == WINED3DRTYPE_TEXTURE) { - /* Texture allows: - * - D3DUSAGE_AUTOGENMIPMAP - * - D3DUSAGE_DEPTHSTENCIL - * - D3DUSAGE_DMAP - * - D3DUSAGE_DYNAMIC - * - D3DUSAGE_NONSECURE (d3d9ex) - * - D3DUSAGE_RENDERTARGET - * - D3DUSAGE_SOFTWAREPROCESSING - * - D3DUSAGE_TEXTAPI (d3d9ex) - * - D3DUSAGE_QUERY_WRAPANDMIP - */ + case WINED3DRTYPE_TEXTURE: + /* Texture allows: + * - WINED3DUSAGE_AUTOGENMIPMAP + * - WINED3DUSAGE_DEPTHSTENCIL + * - WINED3DUSAGE_DMAP + * - WINED3DUSAGE_DYNAMIC + * - WINED3DUSAGE_NONSECURE (d3d9ex) + * - WINED3DUSAGE_RENDERTARGET + * - WINED3DUSAGE_SOFTWAREPROCESSING + * - WINED3DUSAGE_TEXTAPI (d3d9ex) + * - WINED3DUSAGE_QUERY_WRAPANDMIP + */ + if (SurfaceType != SURFACE_OPENGL) + { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } - if(SurfaceType != SURFACE_OPENGL) { - TRACE("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } + if (!CheckTextureCapability(adapter, format_desc)) + { + TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n"); + return WINED3DERR_NOTAVAILABLE; + } - /* Check if the texture format is around */ - if (CheckTextureCapability(adapter, DeviceType, format_desc)) - { - if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - /* Check for automatic mipmap generation support */ - if (gl_info->supported[SGIS_GENERATE_MIPMAP]) - { - UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP; - } else { - /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */ + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + /* When autogenmipmap isn't around continue and return + * WINED3DOK_NOAUTOGEN instead of D3D_OK. */ TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n"); - } + else + UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP; } - /* Always report dynamic locking */ - if(Usage & WINED3DUSAGE_DYNAMIC) + /* Always report dynamic locking. */ + if (Usage & WINED3DUSAGE_DYNAMIC) UsageCaps |= WINED3DUSAGE_DYNAMIC; - if(Usage & WINED3DUSAGE_RENDERTARGET) { - if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) + if (Usage & WINED3DUSAGE_RENDERTARGET) + { + if (!CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc)) { - UsageCaps |= WINED3DUSAGE_RENDERTARGET; - } else { TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); - return WINED3DERR_NOTAVAILABLE; - } + return WINED3DERR_NOTAVAILABLE; + } + UsageCaps |= WINED3DUSAGE_RENDERTARGET; } - /* Always report software processing */ - if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + /* Always report software processing. */ + if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING) UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; - /* Check QUERY_FILTER support */ - if(Usage & WINED3DUSAGE_QUERY_FILTER) { - if (CheckFilterCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_FILTER) + { + if (!CheckFilterCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_FILTER; - } else { TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; } - /* Check QUERY_LEGACYBUMPMAP support */ - if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) { - if (CheckBumpMapCapability(adapter, DeviceType, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) + { + if (!CheckBumpMapCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP; - } else { TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP; } - /* Check QUERY_POSTPIXELSHADER_BLENDING support */ - if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { - if (CheckPostPixelShaderBlendingCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) + { + if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; - } else { TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; } - /* Check QUERY_SRGBREAD support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { - if (CheckSrgbReadCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) + { + if (!CheckSrgbReadCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; - } else { TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; } - /* Check QUERY_SRGBWRITE support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { - if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE) + { + if (!CheckSrgbWriteCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; - } else { TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; } - /* Check QUERY_VERTEXTEXTURE support */ - if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { - if (CheckVertexTextureCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) + { + if (!CheckVertexTextureCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; - } else { TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; } - /* Check QUERY_WRAPANDMIP support */ - if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { - if (CheckWrapAndMipCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) + { + if (!CheckWrapAndMipCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; - } else { TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; } - if(Usage & WINED3DUSAGE_DEPTHSTENCIL) { - if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc)) + if (Usage & WINED3DUSAGE_DEPTHSTENCIL) + { + if (!CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc)) { - UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; - } else { TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n"); return WINED3DERR_NOTAVAILABLE; } + if ((format_desc->Flags & WINED3DFMT_FLAG_SHADOW) && !gl_info->supported[ARB_SHADOW]) + { + TRACE_(d3d_caps)("[FAILED] - No shadow sampler support.\n"); + return WINED3DERR_NOTAVAILABLE; + } + UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; } - } else { - TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n"); - return WINED3DERR_NOTAVAILABLE; - } - } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) { - /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented. - * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too. - * - * Volumetexture allows: - * - D3DUSAGE_DYNAMIC - * - D3DUSAGE_NONSECURE (d3d9ex) - * - D3DUSAGE_SOFTWAREPROCESSING - * - D3DUSAGE_QUERY_WRAPANDMIP - */ + break; - if(SurfaceType != SURFACE_OPENGL) { - TRACE("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } + case WINED3DRTYPE_VOLUMETEXTURE: + case WINED3DRTYPE_VOLUME: + /* Volume is to VolumeTexture what Surface is to Texture, but its + * usage caps are not documented. Most driver seem to offer + * (nearly) the same on Volume and VolumeTexture, so do that too. + * + * Volumetexture allows: + * - D3DUSAGE_DYNAMIC + * - D3DUSAGE_NONSECURE (d3d9ex) + * - D3DUSAGE_SOFTWAREPROCESSING + * - D3DUSAGE_QUERY_WRAPANDMIP + */ + if (SurfaceType != SURFACE_OPENGL) + { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } - /* Check volume texture and volume usage caps */ - if (gl_info->supported[EXT_TEXTURE3D]) - { - if (!CheckTextureCapability(adapter, DeviceType, format_desc)) + if (!gl_info->supported[EXT_TEXTURE3D]) + { + TRACE_(d3d_caps)("[FAILED] - No volume texture support\n"); + return WINED3DERR_NOTAVAILABLE; + } + + if (!CheckTextureCapability(adapter, format_desc)) { TRACE_(d3d_caps)("[FAILED] - Format not supported\n"); return WINED3DERR_NOTAVAILABLE; } - /* Always report dynamic locking */ - if(Usage & WINED3DUSAGE_DYNAMIC) + /* Filter formats that need conversion; For one part, this + * conversion is unimplemented, and volume textures are huge, so + * it would be a big performance hit. Unless we hit an application + * needing one of those formats, don't advertize them to avoid + * leading applications into temptation. The windows drivers don't + * support most of those formats on volumes anyway, except for + * WINED3DFMT_R32_FLOAT. */ + switch (CheckFormat) + { + case WINED3DFMT_P8_UINT: + case WINED3DFMT_L4A4_UNORM: + case WINED3DFMT_R32_FLOAT: + case WINED3DFMT_R16_FLOAT: + case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: + case WINED3DFMT_R5G5_SNORM_L6_UNORM: + case WINED3DFMT_R16G16_UNORM: + TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); + return WINED3DERR_NOTAVAILABLE; + + case WINED3DFMT_R8G8B8A8_SNORM: + case WINED3DFMT_R16G16_SNORM: + if (!gl_info->supported[NV_TEXTURE_SHADER]) + { + TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); + return WINED3DERR_NOTAVAILABLE; + } + break; + + case WINED3DFMT_R8G8_SNORM: + if (!gl_info->supported[NV_TEXTURE_SHADER]) + { + TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); + return WINED3DERR_NOTAVAILABLE; + } + break; + + case WINED3DFMT_DXT1: + case WINED3DFMT_DXT2: + case WINED3DFMT_DXT3: + case WINED3DFMT_DXT4: + case WINED3DFMT_DXT5: + /* The GL_EXT_texture_compression_s3tc spec requires that + * loading an s3tc compressed texture results in an error. + * While the D3D refrast does support s3tc volumes, at + * least the nvidia windows driver does not, so we're free + * not to support this format. */ + TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n"); + return WINED3DERR_NOTAVAILABLE; + + default: + /* Do nothing, continue with checking the format below */ + break; + } + + /* Always report dynamic locking. */ + if (Usage & WINED3DUSAGE_DYNAMIC) UsageCaps |= WINED3DUSAGE_DYNAMIC; - /* Always report software processing */ - if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + /* Always report software processing. */ + if (Usage & WINED3DUSAGE_SOFTWAREPROCESSING) UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; - /* Check QUERY_FILTER support */ - if(Usage & WINED3DUSAGE_QUERY_FILTER) { - if (CheckFilterCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_FILTER) + { + if (!CheckFilterCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_FILTER; - } else { TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; } - /* Check QUERY_POSTPIXELSHADER_BLENDING support */ - if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { - if (CheckPostPixelShaderBlendingCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) + { + if (!CheckPostPixelShaderBlendingCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; - } else { TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; } - /* Check QUERY_SRGBREAD support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { - if (CheckSrgbReadCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) + { + if (!CheckSrgbReadCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; - } else { TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; } - /* Check QUERY_SRGBWRITE support */ - if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { - if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_SRGBWRITE) + { + if (!CheckSrgbWriteCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; - } else { TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; } - /* Check QUERY_VERTEXTEXTURE support */ - if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { - if (CheckVertexTextureCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) + { + if (!CheckVertexTextureCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; - } else { TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); return WINED3DERR_NOTAVAILABLE; } + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; } - /* Check QUERY_WRAPANDMIP support */ - if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { - if (CheckWrapAndMipCapability(adapter, format_desc)) + if (Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) + { + if (!CheckWrapAndMipCapability(adapter, format_desc)) { - UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; - } else { TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); return WINED3DERR_NOTAVAILABLE; } - } - } else { - TRACE_(d3d_caps)("[FAILED] - No volume texture support\n"); - return WINED3DERR_NOTAVAILABLE; - } - - /* Filter formats that need conversion; For one part, this conversion is unimplemented, - * and volume textures are huge, so it would be a big performance hit. Unless we hit an - * app needing one of those formats, don't advertize them to avoid leading apps into - * temptation. The windows drivers don't support most of those formats on volumes anyway, - * except of R32F. - */ - switch(CheckFormat) { - case WINED3DFMT_P8_UINT: - case WINED3DFMT_L4A4_UNORM: - case WINED3DFMT_R32_FLOAT: - case WINED3DFMT_R16_FLOAT: - case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: - case WINED3DFMT_R5G5_SNORM_L6_UNORM: - case WINED3DFMT_R16G16_UNORM: - TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); - return WINED3DERR_NOTAVAILABLE; - - case WINED3DFMT_R8G8B8A8_SNORM: - case WINED3DFMT_R16G16_SNORM: - if (!gl_info->supported[NV_TEXTURE_SHADER]) - { - TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); - return WINED3DERR_NOTAVAILABLE; + UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; } break; - case WINED3DFMT_R8G8_SNORM: - if (!gl_info->supported[NV_TEXTURE_SHADER]) - { - TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); - return WINED3DERR_NOTAVAILABLE; - } - break; - - case WINED3DFMT_DXT1: - case WINED3DFMT_DXT2: - case WINED3DFMT_DXT3: - case WINED3DFMT_DXT4: - case WINED3DFMT_DXT5: - /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc - * compressed texture results in an error. While the D3D refrast does - * support s3tc volumes, at least the nvidia windows driver does not, so - * we're free not to support this format. - */ - TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n"); - return WINED3DERR_NOTAVAILABLE; - - default: - /* Do nothing, continue with checking the format below */ - break; - } - } else if(RType == WINED3DRTYPE_BUFFER){ - /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */ - TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n"); - return WINED3DERR_NOTAVAILABLE; + default: + FIXME_(d3d_caps)("Unhandled resource type %s.\n", debug_d3dresourcetype(RType)); + return WINED3DERR_NOTAVAILABLE; } - /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which - * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other - * usage flags match. */ - if(UsageCaps == Usage) { + /* When the UsageCaps exactly matches Usage return WINED3D_OK except for + * the situation in which WINED3DUSAGE_AUTOGENMIPMAP isn't around, then + * WINED3DOK_NOAUTOGEN is returned if all the other usage flags match. */ + if (UsageCaps == Usage) return WINED3D_OK; - } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){ + if (UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) return WINED3DOK_NOAUTOGEN; - } else { - TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps); - return WINED3DERR_NOTAVAILABLE; - } + + TRACE_(d3d_caps)("[FAILED] - Usage %#x requested for CheckFormat %s and RType %s but only %#x is available\n", + Usage, debug_d3dformat(CheckFormat), debug_d3dresourcetype(RType), UsageCaps); + + return WINED3DERR_NOTAVAILABLE; } static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx, @@ -4204,13 +4223,14 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING; /* TODO: WINED3DPMISCCAPS_NULLREFERENCE - WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS WINED3DPMISCCAPS_FOGANDSPECULARALPHA WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS WINED3DPMISCCAPS_FOGVERTEXCLAMPED */ if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE]) pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND; + if (gl_info->supported[EXT_DRAW_BUFFERS2]) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS; pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER | WINED3DPRASTERCAPS_PAT | @@ -4517,10 +4537,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DPTFILTERCAPS_MAGFLINEAR; pCaps->VertexTextureFilterCaps = 0; - memset(&shader_caps, 0, sizeof(shader_caps)); adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps); - - memset(&fragment_caps, 0, sizeof(fragment_caps)); adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps); /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */ @@ -4551,13 +4568,6 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages; pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures; - pCaps->VS20Caps = shader_caps.VS20Caps; - pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted; - pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots; - pCaps->PS20Caps = shader_caps.PS20Caps; - pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted; - pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots; - /* The following caps are shader specific, but they are things we cannot detect, or which * are the same among all shader models. So to avoid code duplication set the shader version * specific, but otherwise constant caps here @@ -4959,7 +4969,7 @@ static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info) } } -BOOL InitAdapters(IWineD3DImpl *This) +static BOOL InitAdapters(IWineD3DImpl *This) { static HMODULE mod_gl; BOOL ret; @@ -5120,17 +5130,6 @@ BOOL InitAdapters(IWineD3DImpl *This) cfgs->doubleBuffer = values[9]; cfgs->auxBuffers = values[10]; - cfgs->pbufferDrawable = FALSE; - /* Check for pbuffer support when it is around as - * wglGetPixelFormatAttribiv fails for unknown attributes. */ - if (gl_info->supported[WGL_ARB_PBUFFER]) - { - int attrib = WGL_DRAW_TO_PBUFFER_ARB; - int value; - if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value))) - cfgs->pbufferDrawable = value; - } - cfgs->numSamples = 0; /* Check multisample support */ if (gl_info->supported[ARB_MULTISAMPLE]) @@ -5145,7 +5144,11 @@ BOOL InitAdapters(IWineD3DImpl *This) } } - TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, samples=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable, cfgs->pbufferDrawable); + TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, " + "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n", + cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, + cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, + cfgs->depthSize, cfgs->stencilSize, cfgs->numSamples, cfgs->windowDrawable); cfgs++; } } @@ -5182,14 +5185,17 @@ BOOL InitAdapters(IWineD3DImpl *This) cfgs->colorSize = ppfd.cColorBits; cfgs->depthSize = ppfd.cDepthBits; cfgs->stencilSize = ppfd.cStencilBits; - cfgs->pbufferDrawable = 0; cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0; cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB; cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0; cfgs->auxBuffers = ppfd.cAuxBuffers; cfgs->numSamples = 0; - TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable); + TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, " + "depth=%d, stencil=%d, windowDrawable=%d\n", + cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, + cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, + cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable); cfgs++; adapter->nCfgs++; } @@ -5261,7 +5267,7 @@ nogl_adapter: * IWineD3D VTbl follows **********************************************************/ -const IWineD3DVtbl IWineD3D_Vtbl = +static const struct IWineD3DVtbl IWineD3D_Vtbl = { /* IUnknown */ IWineD3DImpl_QueryInterface, @@ -5291,3 +5297,23 @@ const struct wined3d_parent_ops wined3d_null_parent_ops = { wined3d_null_wined3d_object_destroyed, }; + +HRESULT wined3d_init(IWineD3DImpl *wined3d, UINT version, IUnknown *parent) +{ + wined3d->lpVtbl = &IWineD3D_Vtbl; + wined3d->dxVersion = version; + wined3d->ref = 1; + wined3d->parent = parent; + + if (!InitAdapters(wined3d)) + { + WARN("Failed to initialize adapters.\n"); + if (version > 7) + { + MESSAGE("Direct3D%u is not available without OpenGL.\n", version); + return E_FAIL; + } + } + + return WINED3D_OK; +} diff --git a/reactos/dll/directx/wine/wined3d/drawprim.c b/reactos/dll/directx/wine/wined3d/drawprim.c index b29d012b9d1..b36ef5b49ae 100644 --- a/reactos/dll/directx/wine/wined3d/drawprim.c +++ b/reactos/dll/directx/wine/wined3d/drawprim.c @@ -28,7 +28,6 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); -#define GLINFO_LOCATION This->adapter->gl_info #include #include @@ -71,7 +70,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context UINT vx_index; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const UINT *streamOffset = This->stateBlock->streamOffset; - long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; + LONG SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; BOOL pixelShader = use_ps(This->stateBlock); BOOL specular_fog = FALSE; const BYTE *texCoords[WINED3DDP_MAXTEXCOORD]; @@ -85,14 +84,14 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context TRACE("Using slow vertex array code\n"); /* Variable Initialization */ - if (idxSize != 0) { - /* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer. - * If the index buffer has no vbo(not supported or other reason), or with user pointer drawing - * idxData will be != NULL - */ - if(idxData == NULL) { - idxData = buffer_get_sysmem((struct wined3d_buffer *) This->stateBlock->pIndexData); - } + if (idxSize) + { + /* Immediate mode drawing can't make use of indices in a vbo - get the + * data from the index buffer. If the index buffer has no vbo (not + * supported or other reason), or with user pointer drawing idxData + * will be non-NULL. */ + if (!idxData) + idxData = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->pIndexData, gl_info); if (idxSize == 2) pIdxBufS = idxData; else pIdxBufL = idxData; @@ -102,7 +101,6 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context } /* Start drawing in GL */ - VTRACE(("glBegin(%x)\n", glPrimType)); glBegin(glPrimType); if (si->use_map & (1 << WINED3D_FFP_POSITION)) @@ -226,13 +224,10 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context if (idxData != NULL) { /* Indexed so work out the number of strides to skip */ - if (idxSize == 2) { - VTRACE(("Idx for vertex %u = %u\n", vx_index, pIdxBufS[startIdx+vx_index])); + if (idxSize == 2) SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; - } else { - VTRACE(("Idx for vertex %u = %u\n", vx_index, pIdxBufL[startIdx+vx_index])); + else SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; - } } tmp_tex_mask = tex_mask; @@ -426,7 +421,8 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT startIdx) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + LONG SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; const WORD *pIdxBufS = NULL; const DWORD *pIdxBufL = NULL; UINT vx_index; @@ -434,14 +430,14 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream IWineD3DStateBlockImpl *stateblock = This->stateBlock; const BYTE *ptr; - if (idxSize != 0) { - /* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer. - * If the index buffer has no vbo(not supported or other reason), or with user pointer drawing - * idxData will be != NULL - */ - if(idxData == NULL) { - idxData = buffer_get_sysmem((struct wined3d_buffer *) This->stateBlock->pIndexData); - } + if (idxSize) + { + /* Immediate mode drawing can't make use of indices in a vbo - get the + * data from the index buffer. If the index buffer has no vbo (not + * supported or other reason), or with user pointer drawing idxData + * will be non-NULL. */ + if (!idxData) + idxData = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->pIndexData, gl_info); if (idxSize == 2) pIdxBufS = idxData; else pIdxBufL = idxData; @@ -451,20 +447,16 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream } /* Start drawing in GL */ - VTRACE(("glBegin(%x)\n", glPrimitiveType)); glBegin(glPrimitiveType); for (vx_index = 0; vx_index < numberOfVertices; ++vx_index) { if (idxData != NULL) { /* Indexed so work out the number of strides to skip */ - if (idxSize == 2) { - VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index])); + if (idxSize == 2) SkipnStrides = pIdxBufS[startIdx + vx_index] + stateblock->loadBaseVertexIndex; - } else { - VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index])); + else SkipnStrides = pIdxBufL[startIdx + vx_index] + stateblock->loadBaseVertexIndex; - } } for (i = MAX_ATTRIBS - 1; i >= 0; i--) @@ -543,7 +535,7 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, const struct wine { struct wined3d_buffer *vb = (struct wined3d_buffer *)stateblock->streamSource[si->elements[instancedData[j]].stream_idx]; - ptr += (long) buffer_get_sysmem(vb); + ptr += (ULONG_PTR)buffer_get_sysmem(vb, &This->adapter->gl_info); } send_attribute(This, si->elements[instancedData[j]].format_desc->format, instancedData[j], ptr); @@ -555,7 +547,8 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, const struct wine } } -static inline void remove_vbos(IWineD3DDeviceImpl *This, struct wined3d_stream_info *s) +static inline void remove_vbos(IWineD3DDeviceImpl *This, const struct wined3d_gl_info *gl_info, + struct wined3d_stream_info *s) { unsigned int i; @@ -570,7 +563,7 @@ static inline void remove_vbos(IWineD3DDeviceImpl *This, struct wined3d_stream_i { struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; e->buffer_object = 0; - e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb)); + e->data = (BYTE *)((ULONG_PTR)e->data + (ULONG_PTR)buffer_get_sysmem(vb, gl_info)); } } } @@ -580,7 +573,6 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *target; struct wined3d_context *context; unsigned int i; @@ -591,11 +583,11 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Invalidate the back buffer memory so LockRect will read it the next time */ for (i = 0; i < This->adapter->gl_info.limits.buffers; ++i) { - target = (IWineD3DSurfaceImpl *)This->render_targets[i]; + IWineD3DSurface *target = (IWineD3DSurface *)This->render_targets[i]; if (target) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, NULL); - IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); + IWineD3DSurface_LoadLocation(target, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation(target, SFLAG_INDRAWABLE, TRUE); } } } @@ -603,9 +595,18 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Signals other modules that a drawing is in progress and the stateblock finalized */ This->isInDraw = TRUE; - context = context_acquire(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); + context = context_acquire(This, This->render_targets[0]); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping draw.\n"); + return; + } + + context_apply_draw_state(context, This); - if (This->stencilBufferTarget) { + if (This->depth_stencil) + { /* Note that this depends on the context_acquire() call above to set * This->render_offscreen properly. We don't currently take the * Z-compare function into account, but we could skip loading the @@ -614,9 +615,33 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE] || This->stateBlock->renderState[WINED3DRS_ZENABLE]) - surface_load_ds_location(This->stencilBufferTarget, context, location); - if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) - surface_modify_ds_location(This->stencilBufferTarget, location); + { + RECT current_rect, draw_rect, r; + + if (location == SFLAG_DS_ONSCREEN && This->depth_stencil != This->onscreen_depth_stencil) + device_switch_onscreen_ds(This, context, This->depth_stencil); + + if (This->depth_stencil->Flags & location) + SetRect(¤t_rect, 0, 0, + This->depth_stencil->ds_current_size.cx, + This->depth_stencil->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); + + device_get_draw_rect(This, &draw_rect); + + IntersectRect(&r, &draw_rect, ¤t_rect); + if (!EqualRect(&r, &draw_rect)) + surface_load_ds_location(This->depth_stencil, context, location); + + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) + { + surface_modify_ds_location(This->depth_stencil, location, + This->depth_stencil->ds_current_size.cx, + This->depth_stencil->ds_current_size.cy); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)This->depth_stencil, SFLAG_INDRAWABLE, TRUE); + } + } } /* Ok, we will be updating the screen from here onwards so grab the lock */ @@ -659,7 +684,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT if(emulation) { stream_info = &stridedlcl; memcpy(&stridedlcl, &This->strided_streams, sizeof(stridedlcl)); - remove_vbos(This, &stridedlcl); + remove_vbos(This, context->gl_info, &stridedlcl); } } @@ -691,7 +716,12 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Finished updating the screen, restore lock */ LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + for(i = 0; i < This->num_buffer_queries; i++) + { + wined3d_event_query_issue(This->buffer_queries[i], This); + } + + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); @@ -700,14 +730,14 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Diagnostics */ #ifdef SHOW_FRAME_MAKEUP { - static long int primCounter = 0; + static LONG primCounter = 0; /* NOTE: set primCounter to the value reported by drawprim before you want to to write frame makeup to /tmp */ if (primCounter >= 0) { WINED3DLOCKED_RECT r; char buffer[80]; IWineD3DSurface_LockRect(This->render_targets[0], &r, NULL, WINED3DLOCK_READONLY); - sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter); + sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter); TRACE("Saving screenshot %s\n", buffer); IWineD3DSurface_SaveSnapshot(This->render_targets[0], buffer); IWineD3DSurface_UnlockRect(This->render_targets[0]); @@ -718,7 +748,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT int textureNo; for (textureNo = 0; textureNo < MAX_COMBINED_SAMPLERS; ++textureNo) { if (This->stateBlock->textures[textureNo] != NULL) { - sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo); + sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo); TRACE("Saving texture %s\n", buffer); if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) { IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur); @@ -732,7 +762,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT } #endif } - TRACE("drawprim #%ld\n", primCounter); + TRACE("drawprim #%d\n", primCounter); ++primCounter; } #endif @@ -788,7 +818,8 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, /* Simply activate the context for blitting. This disables all the things we don't want and * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the * patch (as opposed to normal draws) will most likely need different changes anyway. */ - context = context_acquire(This, NULL, CTXUSAGE_BLIT); + context = context_acquire(This, NULL); + context_apply_blit_state(context, This); /* First, locate the position data. This is provided in a vertex buffer in the stateblock. * Beware of vbos @@ -800,7 +831,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, { struct wined3d_buffer *vb; vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; - e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb)); + e->data = (BYTE *)((ULONG_PTR)e->data + (ULONG_PTR)buffer_get_sysmem(vb, context->gl_info)); } vtxStride = e->stride; data = e->data + diff --git a/reactos/dll/directx/wine/wined3d/glsl_shader.c b/reactos/dll/directx/wine/wined3d/glsl_shader.c index cb23ee6aa0e..056e9adb45a 100644 --- a/reactos/dll/directx/wine/wined3d/glsl_shader.c +++ b/reactos/dll/directx/wine/wined3d/glsl_shader.c @@ -39,8 +39,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); WINE_DECLARE_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) - #define WINED3D_GLSL_SAMPLE_PROJECTED 0x1 #define WINED3D_GLSL_SAMPLE_RECT 0x2 #define WINED3D_GLSL_SAMPLE_LOD 0x4 @@ -89,7 +87,8 @@ struct shader_glsl_priv { struct constant_heap vconst_heap; struct constant_heap pconst_heap; unsigned char *stack; - GLhandleARB depth_blt_program[tex_type_count]; + GLhandleARB depth_blt_program_full[tex_type_count]; + GLhandleARB depth_blt_program_masked[tex_type_count]; UINT next_constant_version; }; @@ -255,7 +254,7 @@ static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleA /* GL locking is done by the caller. */ static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLhandleARB program) { - GLint i, object_count, source_size; + GLint i, object_count, source_size = -1; GLhandleARB *objects; char *source = NULL; @@ -275,7 +274,7 @@ static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_inf GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &tmp)); - if (!source || source_size < tmp) + if (source_size < tmp) { HeapFree(GetProcessHeap(), 0, source); @@ -719,8 +718,8 @@ static void shader_glsl_load_np2fixup_constants( static void shader_glsl_load_constants(const struct wined3d_context *context, char usePixelShader, char useVertexShader) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DDeviceImpl *device = context->swapchain->device; IWineD3DStateBlockImpl* stateBlock = device->stateBlock; struct shader_glsl_priv *priv = device->shader_priv; @@ -807,7 +806,7 @@ static void shader_glsl_load_constants(const struct wined3d_context *context, correction_params[1] = 1.0f; } else { /* position is window relative, not viewport relative */ - correction_params[0] = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height; + correction_params[0] = context->current_rt->currentDesc.Height; correction_params[1] = -1.0f; } GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params)); @@ -1034,7 +1033,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont */ FIXME("Cannot find a free uniform for vpos correction params\n"); shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n", - context->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height, + context->render_offscreen ? 0.0f : device->render_targets[0]->currentDesc.Height, context->render_offscreen ? 1.0f : -1.0f); } shader_addline(buffer, "vec4 vpos;\n"); @@ -1048,20 +1047,37 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont switch (reg_maps->sampler_type[i]) { case WINED3DSTT_1D: - shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i); + if (pshader && ps_args->shadow & (1 << i)) + shader_addline(buffer, "uniform sampler1DShadow %csampler%u;\n", prefix, i); + else + shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i); break; case WINED3DSTT_2D: - if(device->stateBlock->textures[i] && - IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) == GL_TEXTURE_RECTANGLE_ARB) { - shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i); - } else { - shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); + if (pshader && ps_args->shadow & (1 << i)) + { + if (device->stateBlock->textures[i] + && IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) + == GL_TEXTURE_RECTANGLE_ARB) + shader_addline(buffer, "uniform sampler2DRectShadow %csampler%u;\n", prefix, i); + else + shader_addline(buffer, "uniform sampler2DShadow %csampler%u;\n", prefix, i); + } + else + { + if (device->stateBlock->textures[i] + && IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) + == GL_TEXTURE_RECTANGLE_ARB) + shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i); + else + shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); } break; case WINED3DSTT_CUBE: + if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported Cube shadow sampler.\n"); shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i); break; case WINED3DSTT_VOLUME: + if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported 3D shadow sampler.\n"); shader_addline(buffer, "uniform sampler3D %csampler%u;\n", prefix, i); break; default: @@ -1642,9 +1658,13 @@ static inline const char *shader_get_comp_op(DWORD op) } } -static void shader_glsl_get_sample_function(const struct wined3d_gl_info *gl_info, - DWORD sampler_type, DWORD flags, glsl_sample_function_t *sample_function) +static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx, + DWORD sampler_idx, DWORD flags, glsl_sample_function_t *sample_function) { + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ctx->reg_maps->sampler_type[sampler_idx]; + const struct wined3d_gl_info *gl_info = ctx->gl_info; + BOOL shadow = shader_is_pshader_version(ctx->reg_maps->shader_version.type) + && (((const struct shader_glsl_ctx_priv *)ctx->backend_data)->cur_ps_args->shadow & (1 << sampler_idx)); BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED; BOOL texrect = flags & WINED3D_GLSL_SAMPLE_RECT; BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD; @@ -1653,115 +1673,225 @@ static void shader_glsl_get_sample_function(const struct wined3d_gl_info *gl_inf /* Note that there's no such thing as a projected cube texture. */ switch(sampler_type) { case WINED3DSTT_1D: - if(lod) { - sample_function->name = projected ? "texture1DProjLod" : "texture1DLod"; - } - else if (grad) + if (shadow) { - if (gl_info->supported[EXT_GPU_SHADER4]) - sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad"; - else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) - sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB"; - else + if (lod) { - FIXME("Unsupported 1D grad function.\n"); - sample_function->name = "unsupported1DGrad"; + sample_function->name = projected ? "shadow1DProjLod" : "shadow1DLod"; } - } - else - { - sample_function->name = projected ? "texture1DProj" : "texture1D"; - } - sample_function->coord_mask = WINED3DSP_WRITEMASK_0; - break; - case WINED3DSTT_2D: - if(texrect) { - if(lod) { - sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod"; - } - else if (grad) + else if (grad) { if (gl_info->supported[EXT_GPU_SHADER4]) - sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad"; + sample_function->name = projected ? "shadow1DProjGrad" : "shadow1DGrad"; else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) - sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB"; + sample_function->name = projected ? "shadow1DProjGradARB" : "shadow1DGradARB"; else { - FIXME("Unsupported RECT grad function.\n"); - sample_function->name = "unsupported2DRectGrad"; + FIXME("Unsupported 1D shadow grad function.\n"); + sample_function->name = "unsupported1DGrad"; } } else { - sample_function->name = projected ? "texture2DRectProj" : "texture2DRect"; + sample_function->name = projected ? "shadow1DProj" : "shadow1D"; } - } else { - if(lod) { - sample_function->name = projected ? "texture2DProjLod" : "texture2DLod"; + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; + } + else + { + if (lod) + { + sample_function->name = projected ? "texture1DProjLod" : "texture1DLod"; } - else if (grad) + else if (grad) { if (gl_info->supported[EXT_GPU_SHADER4]) - sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad"; + sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad"; else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) - sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB"; + sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB"; else { - FIXME("Unsupported 2D grad function.\n"); - sample_function->name = "unsupported2DGrad"; + FIXME("Unsupported 1D grad function.\n"); + sample_function->name = "unsupported1DGrad"; } } else { - sample_function->name = projected ? "texture2DProj" : "texture2D"; + sample_function->name = projected ? "texture1DProj" : "texture1D"; } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0; } - sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; break; - case WINED3DSTT_CUBE: - if(lod) { - sample_function->name = "textureCubeLod"; - } - else if (grad) + + case WINED3DSTT_2D: + if (shadow) { - if (gl_info->supported[EXT_GPU_SHADER4]) - sample_function->name = "textureCubeGrad"; - else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) - sample_function->name = "textureCubeGradARB"; + if (texrect) + { + if (lod) + { + sample_function->name = projected ? "shadow2DRectProjLod" : "shadow2DRectLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "shadow2DRectProjGrad" : "shadow2DRectGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "shadow2DRectProjGradARB" : "shadow2DRectGradARB"; + else + { + FIXME("Unsupported RECT shadow grad function.\n"); + sample_function->name = "unsupported2DRectGrad"; + } + } + else + { + sample_function->name = projected ? "shadow2DRectProj" : "shadow2DRect"; + } + } else { - FIXME("Unsupported Cube grad function.\n"); - sample_function->name = "unsupportedCubeGrad"; + if (lod) + { + sample_function->name = projected ? "shadow2DProjLod" : "shadow2DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "shadow2DProjGrad" : "shadow2DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "shadow2DProjGradARB" : "shadow2DGradARB"; + else + { + FIXME("Unsupported 2D shadow grad function.\n"); + sample_function->name = "unsupported2DGrad"; + } + } + else + { + sample_function->name = projected ? "shadow2DProj" : "shadow2D"; + } } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; } else { - sample_function->name = "textureCube"; + if (texrect) + { + if (lod) + { + sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB"; + else + { + FIXME("Unsupported RECT grad function.\n"); + sample_function->name = "unsupported2DRectGrad"; + } + } + else + { + sample_function->name = projected ? "texture2DRectProj" : "texture2DRect"; + } + } + else + { + if (lod) + { + sample_function->name = projected ? "texture2DProjLod" : "texture2DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB"; + else + { + FIXME("Unsupported 2D grad function.\n"); + sample_function->name = "unsupported2DGrad"; + } + } + else + { + sample_function->name = projected ? "texture2DProj" : "texture2D"; + } + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; } - sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; break; - case WINED3DSTT_VOLUME: - if(lod) { - sample_function->name = projected ? "texture3DProjLod" : "texture3DLod"; + + case WINED3DSTT_CUBE: + if (shadow) + { + FIXME("Unsupported Cube shadow function.\n "); + sample_function->name = "unsupportedCubeShadow"; + sample_function->coord_mask = 0; } - else if (grad) + else { - if (gl_info->supported[EXT_GPU_SHADER4]) - sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad"; - else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) - sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB"; + if (lod) + { + sample_function->name = "textureCubeLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = "textureCubeGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = "textureCubeGradARB"; + else + { + FIXME("Unsupported Cube grad function.\n"); + sample_function->name = "unsupportedCubeGrad"; + } + } else { - FIXME("Unsupported 3D grad function.\n"); - sample_function->name = "unsupported3DGrad"; + sample_function->name = "textureCube"; } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; + } + break; + + case WINED3DSTT_VOLUME: + if (shadow) + { + FIXME("Unsupported 3D shadow function.\n "); + sample_function->name = "unsupported3DShadow"; + sample_function->coord_mask = 0; } else { - sample_function->name = projected ? "texture3DProj" : "texture3D"; + if (lod) + { + sample_function->name = projected ? "texture3DProjLod" : "texture3DLod"; + } + else if (grad) + { + if (gl_info->supported[EXT_GPU_SHADER4]) + sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad"; + else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) + sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB"; + else + { + FIXME("Unsupported 3D grad function.\n"); + sample_function->name = "unsupported3DGrad"; + } + } + else + { + sample_function->name = projected ? "texture3DProj" : "texture3D"; + } + sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; } - sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; break; + default: sample_function->name = ""; sample_function->coord_mask = 0; @@ -2164,16 +2294,26 @@ static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins) { struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src_param; + unsigned int mask_size; DWORD write_mask; char dst_mask[6]; write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask); + mask_size = shader_glsl_get_write_mask_size(write_mask); shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); shader_addline(buffer, "tmp0.x = length(%s);\n", src_param.param_str); shader_glsl_append_dst(buffer, ins); - shader_addline(buffer, "tmp0.x == 0.0 ? (%s * FLT_MAX) : (%s / tmp0.x));", - src_param.param_str, src_param.param_str); + if (mask_size > 1) + { + shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s / tmp0.x));\n", + mask_size, src_param.param_str); + } + else + { + shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s / tmp0.x));\n", + src_param.param_str); + } } /** Process the WINED3DSIO_EXPP instruction in GLSL: @@ -2868,10 +3008,8 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_sample_function_t sample_function; DWORD sample_flags = 0; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type; DWORD sampler_idx; DWORD mask = 0, swizzle; @@ -2879,11 +3017,11 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) * 2.0+: Use provided sampler source. */ if (shader_version < WINED3D_SHADER_VERSION(2,0)) sampler_idx = ins->dst[0].reg.idx; else sampler_idx = ins->src[1].reg.idx; - sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; if (shader_version < WINED3D_SHADER_VERSION(1,4)) { DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS]; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ if (flags & WINED3DTTFF_PROJECTED && sampler_type != WINED3DSTT_CUBE) { @@ -2922,7 +3060,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) sample_flags |= WINED3D_GLSL_SAMPLE_RECT; } - shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function); mask |= sample_function.coord_mask; if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE; @@ -2960,7 +3098,6 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) glsl_sample_function_t sample_function; glsl_src_param_t coord_param, dx_param, dy_param; DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD; - DWORD sampler_type; DWORD sampler_idx; DWORD swizzle = ins->src[1].swizzle; @@ -2971,13 +3108,12 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) } sampler_idx = ins->src[1].reg.idx; - sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; if(deviceImpl->stateBlock->textures[sampler_idx] && IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { sample_flags |= WINED3D_GLSL_SAMPLE_RECT; } - shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function); shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); shader_glsl_add_src_param(ins, &ins->src[2], sample_function.coord_mask, &dx_param); shader_glsl_add_src_param(ins, &ins->src[3], sample_function.coord_mask, &dy_param); @@ -2994,17 +3130,15 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) glsl_sample_function_t sample_function; glsl_src_param_t coord_param, lod_param; DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD; - DWORD sampler_type; DWORD sampler_idx; DWORD swizzle = ins->src[1].swizzle; sampler_idx = ins->src[1].reg.idx; - sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; if(deviceImpl->stateBlock->textures[sampler_idx] && IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { sample_flags |= WINED3D_GLSL_SAMPLE_RECT; } - shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function); shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); @@ -3071,12 +3205,10 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins) * then perform a 1D texture lookup from stage dstregnum, place into dst. */ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) { - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_src_param_t src0_param; glsl_sample_function_t sample_function; DWORD sampler_idx = ins->dst[0].reg.idx; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; UINT mask_size; shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); @@ -3086,7 +3218,7 @@ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) * * It is a dependent read - not valid with conditional NP2 textures */ - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function); mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); switch(mask_size) @@ -3199,18 +3331,16 @@ static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) { - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD reg = ins->dst[0].reg.idx; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; glsl_sample_function_t sample_function; shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function); /* Sample the texture using the calculated coordinates */ shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xy"); @@ -3223,17 +3353,15 @@ static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state; - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_src_param_t src0_param; DWORD reg = ins->dst[0].reg.idx; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; glsl_sample_function_t sample_function; shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); /* Dependent read, not valid with conditional NP2 */ - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function); /* Sample the texture using the calculated coordinates */ shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); @@ -3266,13 +3394,11 @@ static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; DWORD reg = ins->dst[0].reg.idx; glsl_src_param_t src0_param; glsl_src_param_t src1_param; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; - WINED3DSAMPLER_TEXTURE_TYPE stype = ins->ctx->reg_maps->sampler_type[reg]; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; glsl_sample_function_t sample_function; @@ -3285,7 +3411,7 @@ static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str); /* Dependent read, not valid with conditional NP2 */ - shader_glsl_get_sample_function(gl_info, stype, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function); /* Sample the texture */ shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); @@ -3298,13 +3424,11 @@ static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; DWORD reg = ins->dst[0].reg.idx; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; glsl_src_param_t src0_param; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; glsl_sample_function_t sample_function; shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); @@ -3318,7 +3442,7 @@ static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *in shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n"); /* Dependent read, not valid with conditional NP2 */ - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function); /* Sample the texture using the calculated coordinates */ shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz"); @@ -3334,10 +3458,8 @@ static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device; - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_sample_function_t sample_function; glsl_src_param_t coord_param; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type; DWORD sampler_idx; DWORD mask; DWORD flags; @@ -3346,9 +3468,8 @@ static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) sampler_idx = ins->dst[0].reg.idx; flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS]; - sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; /* Dependent read, not valid with conditional NP2 */ - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function); mask = sample_function.coord_mask; shader_glsl_write_mask_to_str(mask, coord_mask); @@ -3407,15 +3528,13 @@ static void shader_glsl_bem(const struct wined3d_shader_instruction *ins) * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) { - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; glsl_sample_function_t sample_function; shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function); shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "%s.wx", src0_param.reg_name); } @@ -3424,15 +3543,13 @@ static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */ static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) { - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; glsl_sample_function_t sample_function; shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function); shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "%s.yz", src0_param.reg_name); } @@ -3441,14 +3558,12 @@ static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */ static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) { - const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; - WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; glsl_sample_function_t sample_function; /* Dependent read, not valid with conditional NP2 */ - shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function); + shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function); shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param); shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, @@ -4453,10 +4568,12 @@ static void set_glsl_shader_program(const struct wined3d_context *context, } /* GL locking is done by the caller */ -static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) +static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type, BOOL masked) { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; + const char *blt_pshader; + static const char *blt_vshader[] = { "#version 120\n" @@ -4468,7 +4585,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, "}\n" }; - static const char *blt_pshaders[tex_type_count] = + static const char *blt_pshaders_full[tex_type_count] = { /* tex_1d */ NULL, @@ -4498,7 +4615,44 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, "}\n", }; - if (!blt_pshaders[tex_type]) + static const char *blt_pshaders_masked[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "#version 120\n" + "uniform sampler2D sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "#version 120\n" + "uniform samplerCube sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n" + "}\n", + /* tex_rect */ + "#version 120\n" + "#extension GL_ARB_texture_rectangle : enable\n" + "uniform sampler2DRect sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + }; + + blt_pshader = masked ? blt_pshaders_masked[tex_type] : blt_pshaders_full[tex_type]; + if (!blt_pshader) { FIXME("tex_type %#x not supported\n", tex_type); tex_type = tex_2d; @@ -4509,7 +4663,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, GL_EXTCALL(glCompileShaderARB(vshader_id)); pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); - GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshaders[tex_type], NULL)); + GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshader, NULL)); GL_EXTCALL(glCompileShaderARB(pshader_id)); program_id = GL_EXTCALL(glCreateProgramObjectARB()); @@ -4530,8 +4684,8 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, /* GL locking is done by the caller */ static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) { - IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DDeviceImpl *device = context->swapchain->device; struct shader_glsl_priv *priv = device->shader_priv; GLhandleARB program_id = 0; GLenum old_vertex_color_clamp, current_vertex_color_clamp; @@ -4571,21 +4725,34 @@ static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS } /* GL locking is done by the caller */ -static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { +static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, + enum tex_types tex_type, const SIZE *ds_mask_size) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + BOOL masked = ds_mask_size->cx && ds_mask_size->cy; struct shader_glsl_priv *priv = This->shader_priv; - GLhandleARB *blt_program = &priv->depth_blt_program[tex_type]; + GLhandleARB *blt_program; + GLint loc; - if (!*blt_program) { - GLint loc; - *blt_program = create_glsl_blt_shader(gl_info, tex_type); + blt_program = masked ? &priv->depth_blt_program_masked[tex_type] : &priv->depth_blt_program_full[tex_type]; + if (!*blt_program) + { + *blt_program = create_glsl_blt_shader(gl_info, tex_type, masked); loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "sampler")); GL_EXTCALL(glUseProgramObjectARB(*blt_program)); GL_EXTCALL(glUniform1iARB(loc, 0)); - } else { + } + else + { GL_EXTCALL(glUseProgramObjectARB(*blt_program)); } + + if (masked) + { + loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "mask")); + GL_EXTCALL(glUniform4fARB(loc, 0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy)); + } } /* GL locking is done by the caller */ @@ -4625,7 +4792,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { return; } - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); gl_info = context->gl_info; if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface) @@ -4644,7 +4811,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { return; } - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); gl_info = context->gl_info; if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface) @@ -4821,9 +4988,13 @@ static void shader_glsl_free(IWineD3DDevice *iface) { ENTER_GL(); for (i = 0; i < tex_type_count; ++i) { - if (priv->depth_blt_program[i]) + if (priv->depth_blt_program_full[i]) + { + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_full[i])); + } + if (priv->depth_blt_program_masked[i]) { - GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program[i])); + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_masked[i])); } } LEAVE_GL(); diff --git a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c index 64bb883d6c8..24cba329f20 100644 --- a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c +++ b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c @@ -28,8 +28,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION stateblock->device->adapter->gl_info - /* GL locking for state handlers is done by the caller. */ static void nvts_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) @@ -137,7 +135,6 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX GLenum portion = is_alpha ? GL_ALPHA : GL_RGB; GLenum target = GL_COMBINER0_NV + stage; GLenum output; - IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* For GLINFO_LOCATION */ TRACE("stage %d, is_alpha %d, op %s, arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n", stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx); @@ -579,6 +576,7 @@ static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, str { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->device->texUnitMap[stage + 1]; + const struct wined3d_gl_info *gl_info = context->gl_info; float mat[2][2]; /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to @@ -587,7 +585,7 @@ static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, str * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix * for stage + 1. Keep the nvrc tex unit mapping in mind too */ - if (mapped_stage < context->gl_info->limits.textures) + if (mapped_stage < gl_info->limits.textures) { GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))"); @@ -606,6 +604,7 @@ static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, str static void nvrc_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0])); @@ -629,6 +628,15 @@ static void nvts_enable(IWineD3DDevice *iface, BOOL enable) { static void nvrc_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps) { + pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP; + + /* The caps below can be supported but aren't handled yet in utils.c + * 'd3dta_to_combiner_input', disable them until support is fixed */ +#if 0 + if (gl_info->supported[NV_REGISTER_COMBINERS2]) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; +#endif + pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | WINED3DTEXOPCAPS_ADDSIGNED | WINED3DTEXOPCAPS_ADDSIGNED2X | @@ -672,14 +680,6 @@ static void nvrc_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct pCaps->MaxTextureBlendStages = min(MAX_TEXTURES, gl_info->limits.general_combiners); pCaps->MaxSimultaneousTextures = gl_info->limits.textures; - - pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; - - /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */ -#if 0 - if (gl_info->supported[NV_REGISTER_COMBINERS2]) - pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; -#endif } static HRESULT nvrc_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } @@ -713,119 +713,119 @@ static BOOL nvts_color_fixup_supported(struct color_fixup_desc fixup) static const struct StateEntryTemplate nvrc_fragmentstate_template[] = { { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), nvts_bumpenvmat }, NV_TEXTURE_SHADER2 }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, NV_TEXTURE_SHADER2 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), nvrc_texfactor }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(0), { STATE_SAMPLER(0), nvts_texdim }, NV_TEXTURE_SHADER2 }, { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), nvts_texdim }, NV_TEXTURE_SHADER2 }, diff --git a/reactos/dll/directx/wine/wined3d/palette.c b/reactos/dll/directx/wine/wined3d/palette.c index 553a08a787b..3fd8be9dd10 100644 --- a/reactos/dll/directx/wine/wined3d/palette.c +++ b/reactos/dll/directx/wine/wined3d/palette.c @@ -74,7 +74,8 @@ static ULONG WINAPI IWineD3DPaletteImpl_Release(IWineD3DPalette *iface) { } /* Not called from the vtable */ -DWORD IWineD3DPaletteImpl_Size(DWORD dwFlags) { +static DWORD IWineD3DPaletteImpl_Size(DWORD dwFlags) +{ switch (dwFlags & SIZE_BITS) { case WINEDDPCAPS_1BIT: return 2; case WINEDDPCAPS_2BIT: return 4; @@ -183,7 +184,7 @@ static HRESULT WINAPI IWineD3DPaletteImpl_GetParent(IWineD3DPalette *iface, IUn return WINED3D_OK; } -const IWineD3DPaletteVtbl IWineD3DPalette_Vtbl = +static const IWineD3DPaletteVtbl IWineD3DPalette_Vtbl = { /*** IUnknown ***/ IWineD3DPaletteImpl_QueryInterface, @@ -195,3 +196,33 @@ const IWineD3DPaletteVtbl IWineD3DPalette_Vtbl = IWineD3DPaletteImpl_GetCaps, IWineD3DPaletteImpl_SetEntries }; + +HRESULT wined3d_palette_init(IWineD3DPaletteImpl *palette, IWineD3DDeviceImpl *device, + DWORD flags, const PALETTEENTRY *entries, IUnknown *parent) +{ + HRESULT hr; + + palette->lpVtbl = &IWineD3DPalette_Vtbl; + palette->ref = 1; + palette->parent = parent; + palette->device = device; + palette->Flags = flags; + + palette->palNumEntries = IWineD3DPaletteImpl_Size(flags); + palette->hpal = CreatePalette((const LOGPALETTE *)&palette->palVersion); + if (!palette->hpal) + { + WARN("Failed to create palette.\n"); + return E_FAIL; + } + + hr = IWineD3DPalette_SetEntries((IWineD3DPalette *)palette, 0, 0, IWineD3DPaletteImpl_Size(flags), entries); + if (FAILED(hr)) + { + WARN("Failed to set palette entries, hr %#x.\n", hr); + DeleteObject(palette->hpal); + return hr; + } + + return WINED3D_OK; +} diff --git a/reactos/dll/directx/wine/wined3d/query.c b/reactos/dll/directx/wine/wined3d/query.c index 3860e2c95b5..b3c77eae692 100644 --- a/reactos/dll/directx/wine/wined3d/query.c +++ b/reactos/dll/directx/wine/wined3d/query.c @@ -25,33 +25,19 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) -static HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query) +BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) { - struct wined3d_event_query *ret; - *query = NULL; - if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE] - && !gl_info->supported[APPLE_FENCE]) return E_NOTIMPL; - - ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); - if (!ret) - { - ERR("Failed to allocate a wined3d event query structure.\n"); - return E_OUTOFMEMORY; - } - ret->context = NULL; - *query = ret; - return WINED3D_OK; + return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE]; } -static void wined3d_event_query_destroy(struct wined3d_event_query *query) +void wined3d_event_query_destroy(struct wined3d_event_query *query) { if (query->context) context_free_event_query(query); HeapFree(GetProcessHeap(), 0, query); } -static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; @@ -72,7 +58,7 @@ static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_e return WINED3D_EVENT_QUERY_WRONG_THREAD; } - context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, query->context->current_rt); gl_info = context->gl_info; ENTER_GL(); @@ -125,7 +111,75 @@ static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_e return ret; } -static void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +{ + struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; + enum wined3d_event_query_result ret; + + TRACE("(%p)\n", query); + + if (!query->context) + { + TRACE("Query not started\n"); + return WINED3D_EVENT_QUERY_NOT_STARTED; + } + gl_info = query->context->gl_info; + + if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC]) + { + /* A glFinish does not reliably wait for draws in other contexts. The caller has + * to find its own way to cope with the thread switch + */ + WARN("Event query finished from wrong thread\n"); + return WINED3D_EVENT_QUERY_WRONG_THREAD; + } + + context = context_acquire(device, query->context->current_rt); + + ENTER_GL(); + if (gl_info->supported[ARB_SYNC]) + { + GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, ~(GLuint64)0)); + checkGLcall("glClientWaitSync"); + + switch (gl_ret) + { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: + ret = WINED3D_EVENT_QUERY_OK; + break; + + /* We don't expect a timeout for a ~584 year wait */ + default: + ERR("glClientWaitSync returned %#x.\n", gl_ret); + ret = WINED3D_EVENT_QUERY_ERROR; + } + } + else if (context->gl_info->supported[APPLE_FENCE]) + { + GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); + checkGLcall("glFinishFenceAPPLE"); + ret = WINED3D_EVENT_QUERY_OK; + } + else if (context->gl_info->supported[NV_FENCE]) + { + GL_EXTCALL(glFinishFenceNV(query->object.id)); + checkGLcall("glFinishFenceNV"); + ret = WINED3D_EVENT_QUERY_OK; + } + else + { + ERR("Event query created without GL support\n"); + ret = WINED3D_EVENT_QUERY_ERROR; + } + LEAVE_GL(); + + context_release(context); + return ret; +} + +void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { const struct wined3d_gl_info *gl_info; struct wined3d_context *context; @@ -135,17 +189,17 @@ static void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3 if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId()) { context_free_event_query(query); - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); context_alloc_event_query(context, query); } else { - context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, query->context->current_rt); } } else { - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); context_alloc_event_query(context, query); } @@ -293,7 +347,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, return S_OK; } - context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, query->context->current_rt); ENTER_GL(); @@ -430,12 +484,12 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D FIXME("Wrong thread, can't restart query.\n"); context_free_occlusion_query(query); - context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, NULL); context_alloc_occlusion_query(context, query); } else { - context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, query->context->current_rt); ENTER_GL(); GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); @@ -446,7 +500,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D else { if (query->context) context_free_occlusion_query(query); - context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, NULL); context_alloc_occlusion_query(context, query); } @@ -470,7 +524,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D } else { - context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, query->context->current_rt); ENTER_GL(); GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); @@ -525,7 +579,6 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device, WINED3DQUERYTYPE type, IUnknown *parent) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - HRESULT hr; switch (type) { @@ -548,9 +601,7 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device, case WINED3DQUERYTYPE_EVENT: TRACE("Event query.\n"); - query->lpVtbl = &IWineD3DEventQuery_Vtbl; - hr = wined3d_event_query_init(gl_info, (struct wined3d_event_query **) &query->extendedData); - if (hr == E_NOTIMPL) + if (!wined3d_event_query_supported(gl_info)) { /* Half-Life 2 needs this query. It does not render the main * menu correctly otherwise. Pretend to support it, faking @@ -558,9 +609,12 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device, * lowering performance. */ FIXME("Event query: Unimplemented, but pretending to be supported.\n"); } - else if(FAILED(hr)) + query->lpVtbl = &IWineD3DEventQuery_Vtbl; + query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_event_query)); + if (!query->extendedData) { - return hr; + ERR("Failed to allocate event query memory.\n"); + return E_OUTOFMEMORY; } break; diff --git a/reactos/dll/directx/wine/wined3d/resource.c b/reactos/dll/directx/wine/wined3d/resource.c index b867586096d..67622a38942 100644 --- a/reactos/dll/directx/wine/wined3d/resource.c +++ b/reactos/dll/directx/wine/wined3d/resource.c @@ -28,7 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); HRESULT resource_init(IWineD3DResource *iface, WINED3DRESOURCETYPE resource_type, - IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, + IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { struct IWineD3DResourceClass *resource = &((IWineD3DResourceImpl *)iface)->resource; @@ -247,11 +247,3 @@ HRESULT resource_get_parent(IWineD3DResource *iface, IUnknown **pParent) *pParent = This->resource.parent; return WINED3D_OK; } - -void dumpResources(struct list *list) { - IWineD3DResourceImpl *resource; - - LIST_FOR_EACH_ENTRY(resource, list, IWineD3DResourceImpl, resource.resource_list_entry) { - FIXME("Leftover resource %p with type %d,%s\n", resource, IWineD3DResource_GetType((IWineD3DResource *) resource), debug_d3dresourcetype(IWineD3DResource_GetType((IWineD3DResource *) resource))); - } -} diff --git a/reactos/dll/directx/wine/wined3d/shader.c b/reactos/dll/directx/wine/wined3d/shader.c index 307cadf804c..f26122af869 100644 --- a/reactos/dll/directx/wine/wined3d/shader.c +++ b/reactos/dll/directx/wine/wined3d/shader.c @@ -721,6 +721,7 @@ static HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct else if (ins.handler_idx == WINED3DSIH_MOVA) reg_maps->usesmova = 1; else if (ins.handler_idx == WINED3DSIH_IFC) reg_maps->usesifc = 1; else if (ins.handler_idx == WINED3DSIH_CALL) reg_maps->usescall = 1; + else if (ins.handler_idx == WINED3DSIH_RCP) reg_maps->usesrcp = 1; limit = ins.src_count + (ins.predicate ? 1 : 0); for (i = 0; i < limit; ++i) @@ -1150,7 +1151,11 @@ void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffe if (ins.dst_count) fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr); /* Predication token */ - if (ins.predicate) ins.predicate = *ptr++; + if (ins.predicate) + { + FIXME("Predicates not implemented.\n"); + ins.predicate = *ptr++; + } /* Other source tokens */ for (i = 0; i < ins.src_count; ++i) @@ -1399,7 +1404,7 @@ static void shader_cleanup(IWineD3DBaseShader *iface) static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {} static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {} -static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {} +static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size) {} static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {} static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {} @@ -1414,8 +1419,11 @@ static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct s { /* Set the shader caps to 0 for the none shader backend */ caps->VertexShaderVersion = 0; + caps->MaxVertexShaderConst = 0; caps->PixelShaderVersion = 0; caps->PixelShader1xMaxValue = 0.0f; + caps->MaxPixelShaderConst = 0; + caps->VSClipping = FALSE; } static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup) @@ -2017,6 +2025,9 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, } args->color_fixup[i] = texture->resource.format_desc->color_fixup; + if (texture->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW) + args->shadow |= 1 << i; + /* Flag samplers that need NP2 texcoord fixup. */ if (!texture->baseTexture.pow2Matrix_identity) { diff --git a/reactos/dll/directx/wine/wined3d/state.c b/reactos/dll/directx/wine/wined3d/state.c index 5efe069bb19..4c6d5bfe025 100644 --- a/reactos/dll/directx/wine/wined3d/state.c +++ b/reactos/dll/directx/wine/wined3d/state.c @@ -35,29 +35,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); -#define GLINFO_LOCATION (*context->gl_info) - /* GL locking for state handlers is done by the caller. */ static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); -static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - /* Used for states which are not mapped to a gl state as-is, but used somehow different, - * e.g as a parameter for drawing, or which are unimplemented in windows d3d - */ - if(STATE_IS_RENDER(state)) { - WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0); - TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]); - } else { - /* Shouldn't have an unknown type here */ - FIXME("%d no direct mapping to gl of state with unknown type\n", state); - } + ERR("Undefined state.\n"); } -static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +static void state_nop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - ERR("Undefined state.\n"); + TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state)); } static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) @@ -108,7 +97,7 @@ static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, stru static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { /* No z test without depth stencil buffers */ - if (!stateblock->device->stencilBufferTarget) + if (!stateblock->device->depth_stencil) { TRACE("No Z buffer - disabling depth test\n"); glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */ @@ -242,7 +231,8 @@ static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, struc static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0]; + IWineD3DSurfaceImpl *target = stateblock->device->render_targets[0]; + const struct wined3d_gl_info *gl_info = context->gl_info; int srcBlend = GL_ZERO; int dstBlend = GL_ZERO; @@ -450,10 +440,7 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state, so it may need updating */ if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) - { - const struct StateEntry *StateTable = stateblock->device->StateTable; - StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); - } + stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); } static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) @@ -463,6 +450,7 @@ static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; float col[4]; TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]); @@ -491,9 +479,8 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) { - IWineD3DSurfaceImpl *surf; - - surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0]; + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0]; + IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0]; if (surf->CKeyFlags & WINEDDSD_CKSRCBLT) { @@ -506,10 +493,7 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct } if (enable_ckey || context->last_was_ckey) - { - const struct StateEntry *StateTable = stateblock->device->StateTable; - StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); - } + stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); context->last_was_ckey = enable_ckey; if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] || @@ -621,12 +605,13 @@ static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, str static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; int blendEquation = GL_FUNC_ADD; int blendEquationAlpha = GL_FUNC_ADD; /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */ if (stateblock->renderState[WINED3DRS_BLENDOPALPHA] - && !context->gl_info->supported[EXT_BLEND_EQUATION_SEPARATE]) + && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE]) { WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n"); return; @@ -779,6 +764,7 @@ static void state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int i; /* Note the texture color applies to all textures whereas @@ -788,7 +774,7 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, str D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); /* And now the default texture color as well */ - for (i = 0; i < context->gl_info->limits.texture_stages; ++i) + for (i = 0; i < gl_info->limits.texture_stages; ++i) { /* Note the WINED3DRS value applies to all textures, but GL has one * per texture, so apply it now ready to be used! @@ -804,6 +790,8 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, str static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass) { + const struct wined3d_gl_info *gl_info = context->gl_info; + glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); GL_EXTCALL(glActiveStencilFaceEXT(face)); @@ -831,7 +819,7 @@ static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struc GLint stencilPass_ccw = GL_KEEP; /* No stencil test without a stencil buffer. */ - if (!stateblock->device->stencilBufferTarget) + if (!stateblock->device->depth_stencil) { glDisable(GL_STENCIL_TEST); checkGLcall("glDisable GL_STENCIL_TEST"); @@ -914,7 +902,8 @@ static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struc static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - DWORD mask = stateblock->device->stencilBufferTarget ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0; + DWORD mask = stateblock->device->depth_stencil ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0; + const struct wined3d_gl_info *gl_info = context->gl_info; GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); checkGLcall("glActiveStencilFaceEXT(GL_BACK)"); @@ -927,7 +916,7 @@ static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - DWORD mask = stateblock->device->stencilBufferTarget ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0; + DWORD mask = stateblock->device->depth_stencil ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0; glStencilMask(mask); checkGLcall("glStencilMask"); @@ -1402,7 +1391,9 @@ static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, st static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - union { + const struct wined3d_gl_info *gl_info = context->gl_info; + union + { DWORD d; float f; } min, max; @@ -1423,7 +1414,9 @@ static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - union { + const struct wined3d_gl_info *gl_info = context->gl_info; + union + { DWORD d; float f; } min, max; @@ -1525,30 +1518,60 @@ static void state_debug_monitor(DWORD state, IWineD3DStateBlockImpl *stateblock, static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE]; + DWORD mask0 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE]; + DWORD mask1 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE1]; + DWORD mask2 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE2]; + DWORD mask3 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]; TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", - Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0, - Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0, - Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0, - Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0); - glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, - Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, - Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, - Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE); + mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0); + glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE); checkGLcall("glColorMask(...)"); - /* depends on WINED3DRS_COLORWRITEENABLE. */ - if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F || - stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F || - stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) { - ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", - stateblock->renderState[WINED3DRS_COLORWRITEENABLE1], - stateblock->renderState[WINED3DRS_COLORWRITEENABLE2], - stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]); + if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0) + || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf))) + { + FIXME("WINED3DRS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n", + mask0, mask1, mask2, mask3); + FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n"); } } +static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask) +{ + GL_EXTCALL(glColorMaskIndexedEXT(index, + mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE)); +} + +static void state_colorwrite0(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 0, stateblock->renderState[WINED3DRS_COLORWRITEENABLE]); +} + +static void state_colorwrite1(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 1, stateblock->renderState[WINED3DRS_COLORWRITEENABLE1]); +} + +static void state_colorwrite2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 2, stateblock->renderState[WINED3DRS_COLORWRITEENABLE2]); +} + +static void state_colorwrite3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 3, stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]); +} + static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) { @@ -1706,6 +1729,12 @@ static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, str } } +static void state_zvisible(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + if (stateblock->renderState[WINED3DRS_ZVISIBLE]) + FIXME("WINED3DRS_ZVISIBLE not implemented.\n"); +} + static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) { @@ -1843,13 +1872,6 @@ static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) -{ - if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) { - FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n"); - } -} - static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) { @@ -3083,9 +3105,8 @@ void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) { - IWineD3DSurfaceImpl *surf; - - surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0]; + IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0]; if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask) { @@ -3157,6 +3178,7 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, s { DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->device->texUnitMap[texUnit]; + const struct wined3d_gl_info *gl_info = context->gl_info; BOOL generated; int coordIdx; @@ -3168,7 +3190,7 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, s } if (mapped_stage == WINED3D_UNMAPPED_STAGE) return; - if (mapped_stage >= context->gl_info->limits.textures) return; + if (mapped_stage >= gl_info->limits.textures) return; GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); checkGLcall("glActiveTextureARB"); @@ -3197,21 +3219,20 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, s } } -static void unloadTexCoords(const struct wined3d_context *context) +static void unloadTexCoords(const struct wined3d_gl_info *gl_info) { unsigned int texture_idx; - for (texture_idx = 0; texture_idx < context->gl_info->limits.texture_stages; ++texture_idx) + for (texture_idx = 0; texture_idx < gl_info->limits.texture_stages; ++texture_idx) { GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx)); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } -static void loadTexCoords(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock, +static void loadTexCoords(const struct wined3d_gl_info *gl_info, IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si, GLuint *curVBO) { - const struct wined3d_gl_info *gl_info = context->gl_info; const UINT *offset = stateblock->streamOffset; unsigned int mapped_stage = 0; unsigned int textureNo = 0; @@ -3431,8 +3452,8 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, stru */ GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; - unloadTexCoords(context); - loadTexCoords(context, stateblock, &stateblock->device->strided_streams, &curVBO); + unloadTexCoords(gl_info); + loadTexCoords(gl_info, stateblock, &stateblock->device->strided_streams, &curVBO); } } @@ -3603,10 +3624,8 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct w * while it was enabled, so re-apply them. */ for (i = 0; i < context->gl_info->limits.texture_stages; ++i) { - if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) { - device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply - (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context); - } + if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) + stateblock_apply_state(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context); } context->last_was_pshader = FALSE; } @@ -3750,27 +3769,20 @@ static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, s static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - static BOOL once = FALSE; + WINED3DVERTEXBLENDFLAGS f = stateblock->renderState[WINED3DRS_VERTEXBLEND]; + static unsigned int once; - switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) { - case WINED3DVBF_1WEIGHTS: - case WINED3DVBF_2WEIGHTS: - case WINED3DVBF_3WEIGHTS: - if(!once) { - once = TRUE; - /* TODO: Implement vertex blending in drawStridedSlow */ - FIXME("Vertex blending enabled, but not supported by hardware\n"); - } - break; + if (f == WINED3DVBF_DISABLE) return; - case WINED3DVBF_TWEENING: - WARN("Tweening not supported yet\n"); - } + if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f); + else WARN("Vertex blend flags %#x not supported.\n", f); } static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND]; + const struct wined3d_gl_info *gl_info = context->gl_info; + static unsigned int once; switch(val) { case WINED3DVBF_1WEIGHTS: @@ -3787,7 +3799,7 @@ static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, s if (!stateblock->device->vertexBlendUsed) { unsigned int i; - for (i = 1; i < context->gl_info->limits.blends; ++i) + for (i = 1; i < gl_info->limits.blends; ++i) { if (!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) { @@ -3798,19 +3810,15 @@ static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, s } break; + case WINED3DVBF_TWEENING: + case WINED3DVBF_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 WINED3DVBF_DISABLE: - case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */ glDisable(GL_VERTEX_BLEND_ARB); checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)"); break; - - case WINED3DVBF_TWEENING: - /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have - * vertex weights in the vertices? - * For now we don't report that as supported, so a warn should suffice - */ - WARN("Tweening not supported yet\n"); - break; } } @@ -3975,10 +3983,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock /* This should match any arrays loaded in loadVertexData. * TODO: Only load / unload arrays if we have to. */ -static inline void unloadVertexData(const struct wined3d_context *context) +static inline void unloadVertexData(const struct wined3d_gl_info *gl_info) { - const struct wined3d_gl_info *gl_info = context->gl_info; - glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); @@ -3990,11 +3996,13 @@ static inline void unloadVertexData(const struct wined3d_context *context) { glDisableClientState(GL_WEIGHT_ARRAY_ARB); } - unloadTexCoords(context); + unloadTexCoords(gl_info); } -static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context, int i) +static inline void unload_numbered_array(struct wined3d_context *context, int i) { + const struct wined3d_gl_info *gl_info = context->gl_info; + GL_EXTCALL(glDisableVertexAttribArrayARB(i)); checkGLcall("glDisableVertexAttribArrayARB(reg)"); @@ -4004,7 +4012,7 @@ static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, str /* This should match any arrays loaded in loadNumberedArrays * TODO: Only load / unload arrays if we have to. */ -static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +static inline void unloadNumberedArrays(struct wined3d_context *context) { /* disable any attribs (this is the same for both GLSL and ARB modes) */ GLint maxAttribs = 16; @@ -4016,7 +4024,7 @@ static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, stru if (glGetError() != GL_NO_ERROR) maxAttribs = 16; for (i = 0; i < maxAttribs; ++i) { - unload_numbered_array(stateblock, context, i); + unload_numbered_array(context, i); } } @@ -4036,14 +4044,14 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, for (i = 0; i < MAX_ATTRIBS; i++) { if (!(stream_info->use_map & (1 << i))) { - if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i); + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); continue; } /* Do not load instance data. It will be specified using glTexCoord by drawprim */ if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA) { - if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i); + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); stateblock->device->instancedDraw = TRUE; continue; } @@ -4102,10 +4110,10 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, if (stream_info->elements[i].buffer_object) { vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx]; - ptr += (long) buffer_get_sysmem(vb); + ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info); } - if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i); + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); switch (stream_info->elements[i].format_desc->format) { @@ -4225,11 +4233,6 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1)); - VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n", - WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) , - sd->u.s.blendWeights.dwStride, - sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo])); - if (curVBO != e->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); @@ -4237,8 +4240,13 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB curVBO = e->buffer_object; } - GL_EXTCALL(glWeightPointerARB)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, - e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n", + e->format_desc->gl_vtx_format, + e->format_desc->gl_vtx_type, + e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + GL_EXTCALL(glWeightPointerARB(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx])); checkGLcall("glWeightPointerARB"); @@ -4279,8 +4287,6 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB /* Vertex Pointers -----------------------------------------*/ if (si->use_map & (1 << WINED3D_FFP_POSITION)) { - VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data)); - e = &si->elements[WINED3D_FFP_POSITION]; if (curVBO != e->buffer_object) { @@ -4299,9 +4305,16 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB */ if (!e->buffer_object) { + TRACE("glVertexPointer(3, %#x, %#x, %p);\n", e->format_desc->gl_vtx_type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); - } else { + } + else + { + TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n", + e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); } @@ -4313,8 +4326,6 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB /* Normals -------------------------------------------------*/ if (si->use_map & (1 << WINED3D_FFP_NORMAL)) { - VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data)); - e = &si->elements[WINED3D_FFP_NORMAL]; if (curVBO != e->buffer_object) { @@ -4322,6 +4333,9 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB checkGLcall("glBindBufferARB"); curVBO = e->buffer_object; } + + TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format_desc->gl_vtx_type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); glNormalPointer(e->format_desc->gl_vtx_type, e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); checkGLcall("glNormalPointer(...)"); @@ -4344,8 +4358,6 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB if (si->use_map & (1 << WINED3D_FFP_DIFFUSE)) { - VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data)); - e = &si->elements[WINED3D_FFP_DIFFUSE]; if (curVBO != e->buffer_object) { @@ -4354,6 +4366,9 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB curVBO = e->buffer_object; } + TRACE("glColorPointer(%#x, %#x %#x, %p);\n", + e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); @@ -4369,7 +4384,6 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB if (si->use_map & (1 << WINED3D_FFP_SPECULAR)) { TRACE("setting specular colour\n"); - VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data)); e = &si->elements[WINED3D_FFP_SPECULAR]; if (gl_info->supported[EXT_SECONDARY_COLOR]) @@ -4391,8 +4405,10 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts * 4 component secondary colors use it */ - GL_EXTCALL(glSecondaryColorPointerEXT)(format, type, - e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx])); checkGLcall("glSecondaryColorPointerEXT(format, type, ...)"); } else @@ -4400,25 +4416,29 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB switch(type) { case GL_UNSIGNED_BYTE: - GL_EXTCALL(glSecondaryColorPointerEXT)(3, GL_UNSIGNED_BYTE, - e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx])); 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 */ - GL_EXTCALL(glSecondaryColorPointerEXT)(3, type, - e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride, + e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx])); checkGLcall("glSecondaryColorPointerEXT(3, type, ...)"); } } glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); - } else { - - /* Missing specular color is not critical, no warnings */ - VTRACE(("Specular colour is not supported in this GL implementation\n")); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); } } else @@ -4427,15 +4447,15 @@ static void loadVertexData(const struct wined3d_context *context, IWineD3DStateB { GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); checkGLcall("glSecondaryColor3fEXT(0, 0, 0)"); - } else { - - /* Missing specular color is not critical, no warnings */ - VTRACE(("Specular colour is not supported in this GL implementation\n")); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); } } /* Texture coords -------------------------------------------*/ - loadTexCoords(context, stateblock, si, &curVBO); + loadTexCoords(gl_info, stateblock, si, &curVBO); } static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) @@ -4446,13 +4466,13 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wi if (context->numberedArraysLoaded && !load_numbered) { - unloadNumberedArrays(stateblock, context); + unloadNumberedArrays(context); context->numberedArraysLoaded = FALSE; context->numbered_array_mask = 0; } else if (context->namedArraysLoaded) { - unloadVertexData(context); + unloadVertexData(context->gl_info); context->namedArraysLoaded = FALSE; } @@ -4618,9 +4638,8 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, s context->last_was_vshader = useVertexShaderFunction; - if(updateFog) { - device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context); - } + if (updateFog) stateblock_apply_state(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context); + if(!useVertexShaderFunction) { int i; for(i = 0; i < MAX_TEXTURES; i++) { @@ -4633,7 +4652,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, s static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0]; + IWineD3DSurfaceImpl *target = stateblock->device->render_targets[0]; UINT width, height; WINED3DVIEWPORT vp = stateblock->viewport; @@ -4671,6 +4690,8 @@ static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) { state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context); } + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) + shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); } static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) @@ -4789,7 +4810,7 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { - IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0]; + IWineD3DSurfaceImpl *target = stateblock->device->render_targets[0]; RECT *pRect = &stateblock->scissorRect; UINT height; UINT width; @@ -4812,6 +4833,8 @@ static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { + const struct wined3d_gl_info *gl_info = context->gl_info; + if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) { GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); } else { @@ -4833,17 +4856,17 @@ static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wi } const struct StateEntryTemplate misc_state_template[] = { - { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, - { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_STREAMSRC, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE }, { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE }, { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE }, @@ -4851,58 +4874,59 @@ const struct StateEntryTemplate misc_state_template[] = { * vshader loadings are untied from each other */ { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE }, - { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE }, { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT }, + { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, state_nop }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE }, @@ -4916,9 +4940,9 @@ const struct StateEntryTemplate misc_state_template[] = { { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE }, @@ -4933,35 +4957,35 @@ const struct StateEntryTemplate misc_state_template[] = { { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE }, { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE }, @@ -4969,28 +4993,33 @@ const struct StateEntryTemplate misc_state_template[] = { { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE }, { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite0 }, EXT_DRAW_BUFFERS2 }, { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX }, { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), state_colorwrite1 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), state_colorwrite2 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), state_colorwrite3 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR }, { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZVISIBLE), { STATE_RENDER(WINED3DRS_ZVISIBLE), state_zvisible }, 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 }, @@ -5017,8 +5046,8 @@ const struct StateEntryTemplate misc_state_template[] = { const struct StateEntryTemplate ffp_vertexstate_template[] = { { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, - { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, - { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE }, + { STATE_VSHADER, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE }, /* Clip planes */ { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, @@ -5067,14 +5096,14 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = { /* Transform states follow */ { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE }, { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, - { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE }, { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE }, { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE }, @@ -5349,36 +5378,39 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = { { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, /* Fog */ { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE }, { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND }, { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, - { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, - { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, ARB_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, EXT_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TWEENFACTOR), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_INDEXEDVERTEXBLENDENABLE), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE }, + /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported, * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states. * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix @@ -5412,96 +5444,95 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = { static const struct StateEntryTemplate ffp_fragmentstate_template[] = { { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, - { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, @@ -5512,13 +5543,13 @@ static const struct StateEntryTemplate ffp_fragmentstate_template[] = { { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; -#undef GLINFO_LOCATION /* Context activation is done by the caller. */ static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { } static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps) { + pCaps->PrimitiveMiscCaps = 0; pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | WINED3DTEXOPCAPS_ADDSIGNED | WINED3DTEXOPCAPS_ADDSIGNED2X | @@ -5626,20 +5657,94 @@ static void prune_invalid_states(struct StateEntry *state_table, const struct wi state_table[i].representative = 0; state_table[i].apply = state_undefined; } + + start = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(gl_info->limits.blends)); + last = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)); + for (i = start; i <= last; ++i) + { + state_table[i].representative = 0; + state_table[i].apply = state_undefined; + } } static void validate_state_table(struct StateEntry *state_table) { - unsigned int i; + static const struct + { + DWORD first; + DWORD last; + } + rs_holes[] = + { + { 1, 1}, + { 3, 3}, + { 17, 18}, + { 21, 21}, + { 42, 45}, + { 61, 127}, + {149, 150}, + {169, 169}, + {177, 177}, + {196, 197}, + { 0, 0}, + }; + static const DWORD simple_states[] = + { + STATE_MATERIAL, + STATE_VDECL, + STATE_STREAMSRC, + STATE_INDEXBUFFER, + STATE_VERTEXSHADERCONSTANT, + STATE_PIXELSHADERCONSTANT, + STATE_VSHADER, + STATE_PIXELSHADER, + STATE_VIEWPORT, + STATE_SCISSORRECT, + STATE_FRONTFACE, + }; + unsigned int i, current; + + for (i = STATE_RENDER(1), current = 0; i <= STATE_RENDER(WINEHIGHEST_RENDER_STATE); ++i) + { + if (!rs_holes[current].first || i < STATE_RENDER(rs_holes[current].first)) + { + if (!state_table[i].representative) + ERR("State %s (%#x) should have a representative.\n", debug_d3dstate(i), i); + } + else if (state_table[i].representative) + ERR("State %s (%#x) shouldn't have a representative.\n", debug_d3dstate(i), i); + + if (i == STATE_RENDER(rs_holes[current].last)) ++current; + } + + for (i = 0; i < sizeof(simple_states) / sizeof(*simple_states); ++i) + { + if (!state_table[simple_states[i]].representative) + ERR("State %s (%#x) should have a representative.\n", + debug_d3dstate(simple_states[i]), simple_states[i]); + } for (i = 0; i < STATE_HIGHEST + 1; ++i) { DWORD rep = state_table[i].representative; - if (rep && !state_table[rep].representative) + if (rep) { - ERR("State %s (%#x) has invalid representative %s (%#x).\n", - debug_d3dstate(i), i, debug_d3dstate(rep), rep); - state_table[i].representative = 0; + if (state_table[rep].representative != rep) + { + ERR("State %s (%#x) has invalid representative %s (%#x).\n", + debug_d3dstate(i), i, debug_d3dstate(rep), rep); + state_table[i].representative = 0; + } + + if (rep != i) + { + if (state_table[i].apply) + ERR("State %s (%#x) has both a handler and representative.\n", debug_d3dstate(i), i); + } + else if (!state_table[i].apply) + { + ERR("Self representing state %s (%#x) has no handler.\n", debug_d3dstate(i), i); + } } } } @@ -5696,7 +5801,7 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_ * applying later lines, but do not record anything in the state * table */ - if(!cur[i].content.apply) continue; + if (!cur[i].content.representative) continue; handlers = num_handlers(multistate_funcs[cur[i].state]); multistate_funcs[cur[i].state][handlers] = cur[i].content.apply; diff --git a/reactos/dll/directx/wine/wined3d/stateblock.c b/reactos/dll/directx/wine/wined3d/stateblock.c index 48f9eacc453..1696646849e 100644 --- a/reactos/dll/directx/wine/wined3d/stateblock.c +++ b/reactos/dll/directx/wine/wined3d/stateblock.c @@ -757,7 +757,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) { TRACE("Updating scissor rect.\n"); - targetStateBlock->scissorRect = This->scissorRect; + This->scissorRect = targetStateBlock->scissorRect; } map = This->changed.streamSource; @@ -866,7 +866,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) return WINED3D_OK; } -static void apply_lights(IWineD3DDevice *pDevice, const IWineD3DStateBlockImpl *This) +static void apply_lights(IWineD3DDevice *device, const IWineD3DStateBlockImpl *This) { UINT i; for(i = 0; i < LIGHTMAP_SIZE; i++) { @@ -876,8 +876,8 @@ static void apply_lights(IWineD3DDevice *pDevice, const IWineD3DStateBlockImpl * { const struct wined3d_light_info *light = LIST_ENTRY(e, struct wined3d_light_info, entry); - IWineD3DDevice_SetLight(pDevice, light->OriginalIndex, &light->OriginalParms); - IWineD3DDevice_SetLightEnable(pDevice, light->OriginalIndex, light->glIndex != -1); + IWineD3DDevice_SetLight(device, light->OriginalIndex, &light->OriginalParms); + IWineD3DDevice_SetLightEnable(device, light->OriginalIndex, light->glIndex != -1); } } } @@ -885,58 +885,58 @@ static void apply_lights(IWineD3DDevice *pDevice, const IWineD3DStateBlockImpl * static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) { IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; - IWineD3DDevice *pDevice = (IWineD3DDevice *)This->device; + IWineD3DDevice *device = (IWineD3DDevice *)This->device; unsigned int i; DWORD map; - TRACE("(%p) : Applying state block %p ------------------v\n", This, pDevice); + TRACE("(%p) : Applying state block %p ------------------v\n", This, device); TRACE("Blocktype: %d\n", This->blockType); - if (This->changed.vertexShader) IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader); + if (This->changed.vertexShader) IWineD3DDevice_SetVertexShader(device, This->vertexShader); /* Vertex Shader Constants */ for (i = 0; i < This->num_contained_vs_consts_f; ++i) { - IWineD3DDevice_SetVertexShaderConstantF(pDevice, This->contained_vs_consts_f[i], + IWineD3DDevice_SetVertexShaderConstantF(device, This->contained_vs_consts_f[i], This->vertexShaderConstantF + This->contained_vs_consts_f[i] * 4, 1); } for (i = 0; i < This->num_contained_vs_consts_i; ++i) { - IWineD3DDevice_SetVertexShaderConstantI(pDevice, This->contained_vs_consts_i[i], + IWineD3DDevice_SetVertexShaderConstantI(device, This->contained_vs_consts_i[i], This->vertexShaderConstantI + This->contained_vs_consts_i[i] * 4, 1); } for (i = 0; i < This->num_contained_vs_consts_b; ++i) { - IWineD3DDevice_SetVertexShaderConstantB(pDevice, This->contained_vs_consts_b[i], + IWineD3DDevice_SetVertexShaderConstantB(device, This->contained_vs_consts_b[i], This->vertexShaderConstantB + This->contained_vs_consts_b[i], 1); } - apply_lights(pDevice, This); + apply_lights(device, This); - if (This->changed.pixelShader) IWineD3DDevice_SetPixelShader(pDevice, This->pixelShader); + if (This->changed.pixelShader) IWineD3DDevice_SetPixelShader(device, This->pixelShader); /* Pixel Shader Constants */ for (i = 0; i < This->num_contained_ps_consts_f; ++i) { - IWineD3DDevice_SetPixelShaderConstantF(pDevice, This->contained_ps_consts_f[i], + IWineD3DDevice_SetPixelShaderConstantF(device, This->contained_ps_consts_f[i], This->pixelShaderConstantF + This->contained_ps_consts_f[i] * 4, 1); } for (i = 0; i < This->num_contained_ps_consts_i; ++i) { - IWineD3DDevice_SetPixelShaderConstantI(pDevice, This->contained_ps_consts_i[i], + IWineD3DDevice_SetPixelShaderConstantI(device, This->contained_ps_consts_i[i], This->pixelShaderConstantI + This->contained_ps_consts_i[i] * 4, 1); } for (i = 0; i < This->num_contained_ps_consts_b; ++i) { - IWineD3DDevice_SetPixelShaderConstantB(pDevice, This->contained_ps_consts_b[i], + IWineD3DDevice_SetPixelShaderConstantB(device, This->contained_ps_consts_b[i], This->pixelShaderConstantB + This->contained_ps_consts_b[i], 1); } /* Render */ for (i = 0; i < This->num_contained_render_states; ++i) { - IWineD3DDevice_SetRenderState(pDevice, This->contained_render_states[i], + IWineD3DDevice_SetRenderState(device, This->contained_render_states[i], This->renderState[This->contained_render_states[i]]); } @@ -946,7 +946,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) DWORD stage = This->contained_tss_states[i].stage; DWORD state = This->contained_tss_states[i].state; - IWineD3DDevice_SetTextureStageState(pDevice, stage, state, This->textureState[stage][state]); + IWineD3DDevice_SetTextureStageState(device, stage, state, This->textureState[stage][state]); } /* Sampler states */ @@ -957,12 +957,12 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) DWORD value = This->samplerState[stage][state]; if (stage >= MAX_FRAGMENT_SAMPLERS) stage += WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS; - IWineD3DDevice_SetSamplerState(pDevice, stage, state, value); + IWineD3DDevice_SetSamplerState(device, stage, state, value); } for (i = 0; i < This->num_contained_transform_states; ++i) { - IWineD3DDevice_SetTransform(pDevice, This->contained_transform_states[i], + IWineD3DDevice_SetTransform(device, This->contained_transform_states[i], &This->transforms[This->contained_transform_states[i]]); } @@ -974,40 +974,40 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) if (This->changed.indices) { - IWineD3DDevice_SetIndexBuffer(pDevice, This->pIndexData, This->IndexFmt); - IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex); + IWineD3DDevice_SetIndexBuffer(device, This->pIndexData, This->IndexFmt); + IWineD3DDevice_SetBaseVertexIndex(device, This->baseVertexIndex); } if (This->changed.vertexDecl && This->vertexDecl) { - IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl); + IWineD3DDevice_SetVertexDeclaration(device, This->vertexDecl); } if (This->changed.material) { - IWineD3DDevice_SetMaterial(pDevice, &This->material); + IWineD3DDevice_SetMaterial(device, &This->material); } if (This->changed.viewport) { - IWineD3DDevice_SetViewport(pDevice, &This->viewport); + IWineD3DDevice_SetViewport(device, &This->viewport); } if (This->changed.scissorRect) { - IWineD3DDevice_SetScissorRect(pDevice, &This->scissorRect); + IWineD3DDevice_SetScissorRect(device, &This->scissorRect); } map = This->changed.streamSource; for (i = 0; map; map >>= 1, ++i) { - if (map & 1) IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]); + if (map & 1) IWineD3DDevice_SetStreamSource(device, i, This->streamSource[i], 0, This->streamStride[i]); } map = This->changed.streamFreq; for (i = 0; map; map >>= 1, ++i) { - if (map & 1) IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]); + if (map & 1) IWineD3DDevice_SetStreamSourceFreq(device, i, This->streamFreq[i] | This->streamFlags[i]); } map = This->changed.textures; @@ -1018,7 +1018,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) if (!(map & 1)) continue; stage = i < MAX_FRAGMENT_SAMPLERS ? i : WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS; - IWineD3DDevice_SetTexture(pDevice, stage, This->textures[i]); + IWineD3DDevice_SetTexture(device, stage, This->textures[i]); } map = This->changed.clipplane; @@ -1032,7 +1032,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) clip[1] = This->clipplane[i][1]; clip[2] = This->clipplane[i][2]; clip[3] = This->clipplane[i][3]; - IWineD3DDevice_SetClipPlane(pDevice, i, clip); + IWineD3DDevice_SetClipPlane(device, i, clip); } This->device->stateBlock->lowest_disabled_stage = MAX_TEXTURES - 1; @@ -1044,7 +1044,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) break; } } - TRACE("(%p) : Applied state block %p ------------------^\n", This, pDevice); + TRACE("(%p) : Applied state block %p ------------------^\n", This, device); return WINED3D_OK; } @@ -1052,8 +1052,8 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface) static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) { IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; IWineD3DDevice *device = (IWineD3DDevice *)This->device; - IWineD3DDeviceImpl *ThisDevice = (IWineD3DDeviceImpl *)device; - const struct wined3d_gl_info *gl_info = &ThisDevice->adapter->gl_info; + IWineD3DDeviceImpl *device_impl = (IWineD3DDeviceImpl *)device; + const struct wined3d_gl_info *gl_info = &device_impl->adapter->gl_info; union { WINED3DLINEPATTERN lp; DWORD d; @@ -1070,7 +1070,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat /* Note this may have a large overhead but it should only be executed once, in order to initialize the complete state of the device and all opengl equivalents */ - TRACE("(%p) -----------------------> Setting up device defaults... %p\n", This, ThisDevice); + TRACE("(%p) -----------------------> Setting up device defaults... %p\n", This, device); /* TODO: make a special stateblock type for the primary stateblock (it never gets applied so it doesn't need a real type) */ This->blockType = WINED3DSBT_INIT; @@ -1083,11 +1083,10 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat TRACE("Render states\n"); /* Render states: */ - if (ThisDevice->auto_depth_stencil_buffer != NULL) { + if (device_impl->auto_depth_stencil) IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE, WINED3DZB_TRUE); - } else { + else IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE, WINED3DZB_FALSE); - } IWineD3DDevice_SetRenderState(device, WINED3DRS_FILLMODE, WINED3DFILL_SOLID); IWineD3DDevice_SetRenderState(device, WINED3DRS_SHADEMODE, WINED3DSHADE_GOURAUD); lp.lp.wRepeatFactor = 0; diff --git a/reactos/dll/directx/wine/wined3d/surface.c b/reactos/dll/directx/wine/wined3d/surface.c index d17d35cc16d..0903f6eecaf 100644 --- a/reactos/dll/directx/wine/wined3d/surface.c +++ b/reactos/dll/directx/wine/wined3d/surface.c @@ -34,8 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); WINE_DECLARE_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) - static void surface_cleanup(IWineD3DSurfaceImpl *This) { IWineD3DDeviceImpl *device = This->resource.device; @@ -51,7 +49,7 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This) * target, Uninit3D() will activate a context before doing anything. */ if (device->render_targets && device->render_targets[0]) { - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); } ENTER_GL(); @@ -98,7 +96,7 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This) if (context) context_release(context); } -UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height) +UINT surface_calculate_size(const struct wined3d_format_desc *format_desc, UINT alignment, UINT width, UINT height) { UINT size; @@ -123,13 +121,233 @@ UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT al return size; } +struct blt_info +{ + GLenum binding; + GLenum bind_target; + enum tex_types tex_type; + GLfloat coords[4][3]; +}; + +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 surface_get_blt_info(GLenum target, const RECT *rect_in, GLsizei w, GLsizei h, struct blt_info *info) +{ + GLfloat (*coords)[3] = info->coords; + RECT rect; + struct float_rect f; + + if (rect_in) + rect = *rect_in; + else + { + rect.left = 0; + rect.top = h; + rect.right = w; + rect.bottom = 0; + } + + 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 = tex_2d; + coords[0][0] = (float)rect.left / w; + coords[0][1] = (float)rect.top / h; + coords[0][2] = 0.0f; + + coords[1][0] = (float)rect.right / w; + coords[1][1] = (float)rect.top / h; + coords[1][2] = 0.0f; + + coords[2][0] = (float)rect.left / w; + coords[2][1] = (float)rect.bottom / h; + coords[2][2] = 0.0f; + + coords[3][0] = (float)rect.right / w; + coords[3][1] = (float)rect.bottom / h; + coords[3][2] = 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 = tex_rect; + coords[0][0] = rect.left; coords[0][1] = rect.top; coords[0][2] = 0.0f; + coords[1][0] = rect.right; coords[1][1] = rect.top; coords[1][2] = 0.0f; + coords[2][0] = rect.left; coords[2][1] = rect.bottom; coords[2][2] = 0.0f; + coords[3][0] = rect.right; coords[3][1] = rect.bottom; coords[3][2] = 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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = 1.0f; coords[0][1] = -f.t; coords[0][2] = -f.l; + coords[1][0] = 1.0f; coords[1][1] = -f.t; coords[1][2] = -f.r; + coords[2][0] = 1.0f; coords[2][1] = -f.b; coords[2][2] = -f.l; + coords[3][0] = 1.0f; coords[3][1] = -f.b; coords[3][2] = -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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = -1.0f; coords[0][1] = -f.t; coords[0][2] = f.l; + coords[1][0] = -1.0f; coords[1][1] = -f.t; coords[1][2] = f.r; + coords[2][0] = -1.0f; coords[2][1] = -f.b; coords[2][2] = f.l; + coords[3][0] = -1.0f; coords[3][1] = -f.b; coords[3][2] = 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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = f.l; coords[0][1] = 1.0f; coords[0][2] = f.t; + coords[1][0] = f.r; coords[1][1] = 1.0f; coords[1][2] = f.t; + coords[2][0] = f.l; coords[2][1] = 1.0f; coords[2][2] = f.b; + coords[3][0] = f.r; coords[3][1] = 1.0f; coords[3][2] = 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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = f.l; coords[0][1] = -1.0f; coords[0][2] = -f.t; + coords[1][0] = f.r; coords[1][1] = -1.0f; coords[1][2] = -f.t; + coords[2][0] = f.l; coords[2][1] = -1.0f; coords[2][2] = -f.b; + coords[3][0] = f.r; coords[3][1] = -1.0f; coords[3][2] = -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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = f.l; coords[0][1] = -f.t; coords[0][2] = 1.0f; + coords[1][0] = f.r; coords[1][1] = -f.t; coords[1][2] = 1.0f; + coords[2][0] = f.l; coords[2][1] = -f.b; coords[2][2] = 1.0f; + coords[3][0] = f.r; coords[3][1] = -f.b; coords[3][2] = 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 = tex_cube; + cube_coords_float(&rect, w, h, &f); + + coords[0][0] = -f.l; coords[0][1] = -f.t; coords[0][2] = -1.0f; + coords[1][0] = -f.r; coords[1][1] = -f.t; coords[1][2] = -1.0f; + coords[2][0] = -f.l; coords[2][1] = -f.b; coords[2][2] = -1.0f; + coords[3][0] = -f.r; coords[3][1] = -f.b; coords[3][2] = -1.0f; + break; + } +} + +static inline void surface_get_rect(IWineD3DSurfaceImpl *This, const RECT *rect_in, RECT *rect_out) +{ + if (rect_in) + *rect_out = *rect_in; + else + { + rect_out->left = 0; + rect_out->top = 0; + rect_out->right = This->currentDesc.Width; + rect_out->bottom = This->currentDesc.Height; + } +} + +/* GL locking and context activation is done by the caller */ +void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter) +{ + IWineD3DBaseTextureImpl *texture; + struct blt_info info; + + surface_get_blt_info(src_surface->texture_target, src_rect, src_surface->pow2Width, src_surface->pow2Height, &info); + + glEnable(info.bind_target); + checkGLcall("glEnable(bind_target)"); + + /* Bind the texture */ + glBindTexture(info.bind_target, src_surface->texture_name); + checkGLcall("glBindTexture"); + + /* Filtering for StretchRect */ + glTexParameteri(info.bind_target, GL_TEXTURE_MAG_FILTER, + wined3d_gl_mag_filter(magLookup, Filter)); + checkGLcall("glTexParameteri"); + glTexParameteri(info.bind_target, GL_TEXTURE_MIN_FILTER, + wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE)); + checkGLcall("glTexParameteri"); + glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + checkGLcall("glTexEnvi"); + + /* Draw a quad */ + glBegin(GL_TRIANGLE_STRIP); + glTexCoord3fv(info.coords[0]); + glVertex2i(dst_rect->left, dst_rect->top); + + glTexCoord3fv(info.coords[1]); + glVertex2i(dst_rect->right, dst_rect->top); + + glTexCoord3fv(info.coords[2]); + glVertex2i(dst_rect->left, dst_rect->bottom); + + glTexCoord3fv(info.coords[3]); + glVertex2i(dst_rect->right, dst_rect->bottom); + glEnd(); + + /* Unbind the texture */ + glBindTexture(info.bind_target, 0); + checkGLcall("glBindTexture(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. */ + if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)src_surface, &IID_IWineD3DBaseTexture, (void **)&texture))) + { + texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; + texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; + texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE; + IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture); + } +} + HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); void (*cleanup)(IWineD3DSurfaceImpl *This); unsigned int resource_size; HRESULT hr; @@ -226,7 +444,7 @@ HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, } /* Mark the texture as dirty so that it gets loaded first time around. */ - surface_add_dirty_rect((IWineD3DSurface *)surface, NULL); + surface_add_dirty_rect(surface, NULL); list_init(&surface->renderbuffers); TRACE("surface %p, memory %p, size %u\n", surface, surface->resource.allocatedMemory, surface->resource.size); @@ -243,64 +461,59 @@ HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, return hr; } -static void surface_force_reload(IWineD3DSurface *iface) +static void surface_force_reload(IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - - This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); + surface->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); } -void surface_set_texture_name(IWineD3DSurface *iface, GLuint new_name, BOOL srgb) +void surface_set_texture_name(IWineD3DSurfaceImpl *surface, GLuint new_name, BOOL srgb) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; GLuint *name; DWORD flag; + TRACE("surface %p, new_name %u, srgb %#x.\n", surface, new_name, srgb); + if(srgb) { - name = &This->texture_name_srgb; + name = &surface->texture_name_srgb; flag = SFLAG_INSRGBTEX; } else { - name = &This->texture_name; + name = &surface->texture_name; flag = SFLAG_INTEXTURE; } - TRACE("(%p) : setting texture name %u\n", This, new_name); - if (!*name && new_name) { /* FIXME: We shouldn't need to remove SFLAG_INTEXTURE if the * surface has no texture name yet. See if we can get rid of this. */ - if (This->Flags & flag) + if (surface->Flags & flag) ERR("Surface has SFLAG_INTEXTURE set, but no texture name\n"); - IWineD3DSurface_ModifyLocation(iface, flag, FALSE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, flag, FALSE); } *name = new_name; - surface_force_reload(iface); + surface_force_reload(surface); } -void surface_set_texture_target(IWineD3DSurface *iface, GLenum target) +void surface_set_texture_target(IWineD3DSurfaceImpl *surface, GLenum target) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + TRACE("surface %p, target %#x.\n", surface, target); - TRACE("(%p) : setting target %#x\n", This, target); - - if (This->texture_target != target) + if (surface->texture_target != target) { if (target == GL_TEXTURE_RECTANGLE_ARB) { - This->Flags &= ~SFLAG_NORMCOORD; + surface->Flags &= ~SFLAG_NORMCOORD; } - else if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) + else if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB) { - This->Flags |= SFLAG_NORMCOORD; + surface->Flags |= SFLAG_NORMCOORD; } } - This->texture_target = target; - surface_force_reload(iface); + surface->texture_target = target; + surface_force_reload(surface); } /* Context activation is done by the caller. */ @@ -334,8 +547,9 @@ static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This, BOOL srgb) { /* This function checks if the primary render target uses the 8bit paletted format. */ static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device) { - if (device->render_targets && device->render_targets[0]) { - IWineD3DSurfaceImpl* render_target = (IWineD3DSurfaceImpl*)device->render_targets[0]; + if (device->render_targets && device->render_targets[0]) + { + IWineD3DSurfaceImpl *render_target = device->render_targets[0]; if ((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) && (render_target->resource.format_desc->format == WINED3DFMT_P8_UINT)) return TRUE; @@ -343,15 +557,12 @@ static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device) return FALSE; } -#undef GLINFO_LOCATION - -#define GLINFO_LOCATION This->resource.device->adapter->gl_info - /* This call just downloads data, the caller is responsible for binding the * correct texture. */ /* Context activation is done by the caller. */ -static void surface_download_data(IWineD3DSurfaceImpl *This) { - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; +static void surface_download_data(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info) +{ + const struct wined3d_format_desc *format_desc = This->resource.format_desc; /* Only support read back of converted P8 surfaces */ if (This->Flags & SFLAG_CONVERTED && format_desc->format != WINED3DFMT_P8_UINT) @@ -502,11 +713,28 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { /* This call just uploads data, the caller is responsible for binding the * correct texture. */ /* Context activation is done by the caller. */ -static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) { - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; +static void surface_upload_data(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info, + const struct wined3d_format_desc *format_desc, BOOL srgb, const GLvoid *data) +{ + GLsizei width = This->currentDesc.Width; + GLsizei height = This->currentDesc.Height; + GLenum internal; + + if (srgb) + { + internal = format_desc->glGammaInternal; + } + else if (This->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(This)) + { + internal = format_desc->rtInternal; + } + else + { + internal = format_desc->glInternal; + } TRACE("This %p, internal %#x, width %d, height %d, format %#x, type %#x, data %p.\n", - This, internal, width, height, format, type, data); + This, internal, width, height, format_desc->glFormat, format_desc->glType, data); TRACE("target %#x, level %u, resource size %u.\n", This->texture_target, This->texture_level, This->resource.size); @@ -536,7 +764,7 @@ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsi TRACE("Calling glTexSubImage2D.\n"); glTexSubImage2D(This->texture_target, This->texture_level, - 0, 0, width, height, format, type, data); + 0, 0, width, height, format_desc->glFormat, format_desc->glType, data); checkGLcall("glTexSubImage2D"); } @@ -547,32 +775,58 @@ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsi } LEAVE_GL(); + + if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE) + { + IWineD3DDeviceImpl *device = This->resource.device; + unsigned int i; + + for (i = 0; i < device->numContexts; ++i) + { + context_surface_update(device->contexts[i], This); + } + } } /* This call just allocates the texture, the caller is responsible for binding * the correct texture. */ /* Context activation is done by the caller. */ -static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) { - const struct wined3d_gl_info *gl_info = &This->resource.device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; +static void surface_allocate_surface(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info, + const struct wined3d_format_desc *format_desc, BOOL srgb) +{ BOOL enable_client_storage = FALSE; + GLsizei width = This->pow2Width; + GLsizei height = This->pow2Height; const BYTE *mem = NULL; + GLenum internal; + + if (srgb) + { + internal = format_desc->glGammaInternal; + } + else if (This->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(This)) + { + internal = format_desc->rtInternal; + } + else + { + internal = format_desc->glInternal; + } if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale; TRACE("(%p) : Creating surface (target %#x) level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", This, This->texture_target, This->texture_level, debug_d3dformat(format_desc->format), - internal, width, height, format, type); + internal, width, height, format_desc->glFormat, format_desc->glType); ENTER_GL(); if (gl_info->supported[APPLE_CLIENT_STORAGE]) { - if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_OVERSIZE | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) { + if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) { /* In some cases we want to disable client storage. * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues... - * SFLAG_OVERSIZE: The gl texture is smaller than the allocated memory * SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface * allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively */ @@ -598,7 +852,7 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, else { glTexImage2D(This->texture_target, This->texture_level, - internal, width, height, 0, format, type, mem); + internal, width, height, 0, format_desc->glFormat, format_desc->glType, mem); checkGLcall("glTexImage2D"); } @@ -613,15 +867,15 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, * 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. */ /* GL locking is done by the caller */ -void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - const struct wined3d_gl_info *gl_info = &This->resource.device->adapter->gl_info; +void surface_set_compatible_renderbuffer(IWineD3DSurfaceImpl *surface, unsigned int width, unsigned int height) +{ + const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info; renderbuffer_entry_t *entry; GLuint renderbuffer = 0; unsigned int src_width, src_height; - src_width = This->pow2Width; - src_height = This->pow2Height; + src_width = surface->pow2Width; + src_height = surface->pow2Height; /* A depth stencil smaller than the render target is not valid */ if (width > src_width || height > src_height) return; @@ -630,51 +884,53 @@ void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int wi if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] || (width == src_width && height == src_height)) { - This->current_renderbuffer = NULL; + surface->current_renderbuffer = NULL; return; } /* Look if we've already got a renderbuffer of the correct dimensions */ - LIST_FOR_EACH_ENTRY(entry, &This->renderbuffers, renderbuffer_entry_t, entry) { - if (entry->width == width && entry->height == height) { + LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, renderbuffer_entry_t, entry) + { + if (entry->width == width && entry->height == height) + { renderbuffer = entry->id; - This->current_renderbuffer = entry; + surface->current_renderbuffer = entry; break; } } - if (!renderbuffer) { + if (!renderbuffer) + { gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer); gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, - This->resource.format_desc->glInternal, width, height); + surface->resource.format_desc->glInternal, width, height); entry = HeapAlloc(GetProcessHeap(), 0, sizeof(renderbuffer_entry_t)); entry->width = width; entry->height = height; entry->id = renderbuffer; - list_add_head(&This->renderbuffers, &entry->entry); + list_add_head(&surface->renderbuffers, &entry->entry); - This->current_renderbuffer = entry; + surface->current_renderbuffer = entry; } checkGLcall("set_compatible_renderbuffer"); } -GLenum surface_get_gl_buffer(IWineD3DSurface *iface) +GLenum surface_get_gl_buffer(IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)This->container; + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)surface->container; - TRACE("iface %p.\n", iface); + TRACE("surface %p.\n", surface); - if (!(This->Flags & SFLAG_SWAPCHAIN)) + if (!(surface->Flags & SFLAG_SWAPCHAIN)) { - ERR("Surface %p is not on a swapchain.\n", iface); + ERR("Surface %p is not on a swapchain.\n", surface); return GL_NONE; } - if (swapchain->backBuffer && swapchain->backBuffer[0] == iface) + if (swapchain->back_buffers && swapchain->back_buffers[0] == surface) { if (swapchain->render_to_fbo) { @@ -684,7 +940,7 @@ GLenum surface_get_gl_buffer(IWineD3DSurface *iface) TRACE("Returning GL_BACK\n"); return GL_BACK; } - else if (swapchain->frontBuffer == iface) + else if (surface == swapchain->front_buffer) { TRACE("Returning GL_FRONT\n"); return GL_FRONT; @@ -695,35 +951,35 @@ GLenum surface_get_gl_buffer(IWineD3DSurface *iface) } /* Slightly inefficient way to handle multiple dirty rects but it works :) */ -void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect) +void surface_add_dirty_rect(IWineD3DSurfaceImpl *surface, const RECT *dirty_rect) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DBaseTexture *baseTexture = NULL; - if (!(This->Flags & SFLAG_INSYSMEM) && (This->Flags & SFLAG_INTEXTURE)) - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */); + TRACE("surface %p, dirty_rect %s.\n", surface, wine_dbgstr_rect(dirty_rect)); + + if (!(surface->Flags & SFLAG_INSYSMEM) && (surface->Flags & SFLAG_INTEXTURE)) + /* No partial locking for textures yet. */ + IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, NULL); - IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, TRUE); if (dirty_rect) { - This->dirtyRect.left = min(This->dirtyRect.left, dirty_rect->left); - This->dirtyRect.top = min(This->dirtyRect.top, dirty_rect->top); - This->dirtyRect.right = max(This->dirtyRect.right, dirty_rect->right); - This->dirtyRect.bottom = max(This->dirtyRect.bottom, dirty_rect->bottom); + surface->dirtyRect.left = min(surface->dirtyRect.left, dirty_rect->left); + surface->dirtyRect.top = min(surface->dirtyRect.top, dirty_rect->top); + surface->dirtyRect.right = max(surface->dirtyRect.right, dirty_rect->right); + surface->dirtyRect.bottom = max(surface->dirtyRect.bottom, dirty_rect->bottom); } else { - This->dirtyRect.left = 0; - This->dirtyRect.top = 0; - This->dirtyRect.right = This->currentDesc.Width; - This->dirtyRect.bottom = This->currentDesc.Height; + surface->dirtyRect.left = 0; + surface->dirtyRect.top = 0; + surface->dirtyRect.right = surface->currentDesc.Width; + surface->dirtyRect.bottom = surface->currentDesc.Height; } - TRACE("(%p) : Dirty: yes, Rect:(%d, %d, %d, %d)\n", This, This->dirtyRect.left, - This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom); - /* if the container is a basetexture then mark it dirty. */ - if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture))) + if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)surface, + &IID_IWineD3DBaseTexture, (void **)&baseTexture))) { TRACE("Passing to container\n"); IWineD3DBaseTexture_SetDirty(baseTexture, TRUE); @@ -731,15 +987,59 @@ void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect) } } -static inline BOOL surface_can_stretch_rect(IWineD3DSurfaceImpl *src, IWineD3DSurfaceImpl *dst) +static BOOL surface_convert_color_to_argb(IWineD3DSurfaceImpl *This, DWORD color, DWORD *argb_color) { - return ((src->resource.format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) - || (src->resource.usage & WINED3DUSAGE_RENDERTARGET)) - && ((dst->resource.format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) - || (dst->resource.usage & WINED3DUSAGE_RENDERTARGET)) - && (src->resource.format_desc->format == dst->resource.format_desc->format - || (is_identity_fixup(src->resource.format_desc->color_fixup) - && is_identity_fixup(dst->resource.format_desc->color_fixup))); + IWineD3DDeviceImpl *device = This->resource.device; + + switch(This->resource.format_desc->format) + { + case WINED3DFMT_P8_UINT: + { + DWORD alpha; + + if (primary_render_target_is_p8(device)) + alpha = color << 24; + else + alpha = 0xFF000000; + + if (This->palette) { + *argb_color = (alpha | + (This->palette->palents[color].peRed << 16) | + (This->palette->palents[color].peGreen << 8) | + (This->palette->palents[color].peBlue)); + } else { + *argb_color = alpha; + } + } + break; + + case WINED3DFMT_B5G6R5_UNORM: + { + if (color == 0xFFFF) { + *argb_color = 0xFFFFFFFF; + } else { + *argb_color = ((0xFF000000) | + ((color & 0xF800) << 8) | + ((color & 0x07E0) << 5) | + ((color & 0x001F) << 3)); + } + } + break; + + case WINED3DFMT_B8G8R8_UNORM: + case WINED3DFMT_B8G8R8X8_UNORM: + *argb_color = 0xFF000000 | color; + break; + + case WINED3DFMT_B8G8R8A8_UNORM: + *argb_color = color; + break; + + default: + ERR("Unhandled conversion from %s to ARGB!\n", debug_d3dformat(This->resource.format_desc->format)); + return FALSE; + } + return TRUE; } static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) @@ -764,46 +1064,49 @@ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) IWineD3DSurface IWineD3DResource parts follow **************************************************** */ -void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) +void surface_internal_preload(IWineD3DSurfaceImpl *surface, enum WINED3DSRGB srgb) { /* TODO: check for locks */ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.device; + IWineD3DDeviceImpl *device = surface->resource.device; IWineD3DBaseTexture *baseTexture = NULL; - TRACE("(%p)Checking to see if the container is a base texture\n", This); - if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) { - IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) baseTexture; + TRACE("(%p)Checking to see if the container is a base texture\n", surface); + if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)surface, + &IID_IWineD3DBaseTexture, (void **)&baseTexture))) + { + IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *)baseTexture; TRACE("Passing to container\n"); tex_impl->baseTexture.internal_preload(baseTexture, srgb); IWineD3DBaseTexture_Release(baseTexture); } else { struct wined3d_context *context = NULL; - TRACE("(%p) : About to load surface\n", This); + TRACE("(%p) : About to load surface\n", surface); - if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) context = context_acquire(device, NULL); - if (This->resource.format_desc->format == WINED3DFMT_P8_UINT - || This->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) + if (surface->resource.format_desc->format == WINED3DFMT_P8_UINT + || surface->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) { - if(palette9_changed(This)) { + if (palette9_changed(surface)) + { TRACE("Reloading surface because the d3d8/9 palette was changed\n"); /* TODO: This is not necessarily needed with hw palettized texture support */ - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, NULL); /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */ - IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INTEXTURE, FALSE); } } - IWineD3DSurface_LoadTexture(iface, srgb == SRGB_SRGB ? TRUE : FALSE); + IWineD3DSurface_LoadTexture((IWineD3DSurface *)surface, srgb == SRGB_SRGB ? TRUE : FALSE); - if (This->resource.pool == WINED3DPOOL_DEFAULT) { + if (surface->resource.pool == WINED3DPOOL_DEFAULT) + { /* Tell opengl to try and keep this texture in video ram (well mostly) */ GLclampf tmp; tmp = 0.9f; ENTER_GL(); - glPrioritizeTextures(1, &This->texture_name, &tmp); + glPrioritizeTextures(1, &surface->texture_name, &tmp); LEAVE_GL(); } @@ -811,12 +1114,14 @@ void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) } } -static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { - surface_internal_preload(iface, SRGB_ANY); +static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) +{ + surface_internal_preload((IWineD3DSurfaceImpl *)iface, SRGB_ANY); } /* Context activation is done by the caller. */ -static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { +static void surface_remove_pbo(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info) +{ This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT); This->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); @@ -834,27 +1139,26 @@ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { This->Flags &= ~SFLAG_PBO; } -BOOL surface_init_sysmem(IWineD3DSurface *iface) +BOOL surface_init_sysmem(IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - if(!This->resource.allocatedMemory) + if (!surface->resource.allocatedMemory) { - This->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT); - if(!This->resource.heapMemory) + surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + surface->resource.size + RESOURCE_ALIGNMENT); + if (!surface->resource.heapMemory) { ERR("Out of memory\n"); return FALSE; } - This->resource.allocatedMemory = - (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); + surface->resource.allocatedMemory = + (BYTE *)(((ULONG_PTR)surface->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); } else { - memset(This->resource.allocatedMemory, 0, This->resource.size); + memset(surface->resource.allocatedMemory, 0, surface->resource.size); } - IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, TRUE); return TRUE; } @@ -879,8 +1183,10 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { * or the depth stencil into an FBO the texture or render buffer will be removed * and all flags get lost */ - surface_init_sysmem(iface); - } else { + surface_init_sysmem(This); + } + else + { /* Load the surface into system memory */ IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); @@ -889,13 +1195,12 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DSurface_ModifyLocation(iface, SFLAG_INSRGBTEX, FALSE); This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); gl_info = context->gl_info; /* Destroy PBOs, but load them into real sysmem before */ - if(This->Flags & SFLAG_PBO) { - surface_remove_pbo(This); - } + if (This->Flags & SFLAG_PBO) + surface_remove_pbo(This, gl_info); /* Destroy fbo render buffers. This is needed for implicit render targets, for * all application-created targets the application has to release the surface @@ -936,7 +1241,8 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { /* Read the framebuffer back into the surface */ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, void *dest, UINT pitch) { - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; BYTE *mem; GLint fmt; @@ -964,26 +1270,29 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, v * should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find * context->last_was_blit set on the unlock. */ - context = context_acquire(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); + context = context_acquire(device, This); + context_apply_blit_state(context, device); + gl_info = context->gl_info; + ENTER_GL(); /* Select the correct read buffer, and give some debug output. * There is no need to keep track of the current read buffer or reset it, every part of the code * that reads sets the read buffer as desired. */ - if (surface_is_offscreen((IWineD3DSurface *) This)) + if (surface_is_offscreen(This)) { /* Locking the primary render target which is not on a swapchain(=offscreen render target). * Read from the back buffer */ TRACE("Locking offscreen render target\n"); - glReadBuffer(myDevice->offscreenBuffer); + glReadBuffer(device->offscreenBuffer); srcIsUpsideDown = TRUE; } else { /* Onscreen surfaces are always part of a swapchain */ - GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *)This); + GLenum buffer = surface_get_gl_buffer(This); TRACE("Locking %#x buffer\n", buffer); glReadBuffer(buffer); checkGLcall("glReadBuffer"); @@ -1005,7 +1314,8 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, v { case WINED3DFMT_P8_UINT: { - if(primary_render_target_is_p8(myDevice)) { + if (primary_render_target_is_p8(device)) + { /* In case of P8 render targets the index is stored in the alpha component */ fmt = GL_ALPHA; type = GL_UNSIGNED_BYTE; @@ -1140,7 +1450,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, v * the same color but we have no choice. * In case of P8 render targets, the index is stored in the alpha component so no conversion is needed. */ - if (This->resource.format_desc->format == WINED3DFMT_P8_UINT && !primary_render_target_is_p8(myDevice)) + if (This->resource.format_desc->format == WINED3DFMT_P8_UINT && !primary_render_target_is_p8(device)) { const PALETTEENTRY *pal = NULL; DWORD width = pitch / 3; @@ -1180,20 +1490,18 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, const RECT *rect, v static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) { IWineD3DDeviceImpl *device = This->resource.device; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; - int bpp; - GLenum format, internal, type; - CONVERT_TYPES convert; GLint prevRead; - BOOL alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED; - - d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, srgb); /* Activate the surface to read from. In some situations it isn't the currently active target(e.g. backbuffer * locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any * states in the stateblock, and no driver was found yet that had bugs in that regard. */ - context = context_acquire(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, This); + gl_info = context->gl_info; + + surface_prepare_texture(This, gl_info, srgb); surface_bind_and_dirtify(This, srgb); ENTER_GL(); @@ -1204,9 +1512,9 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) * There is no need to keep track of the current read buffer or reset it, every part of the code * that reads sets the read buffer as desired. */ - if (!surface_is_offscreen((IWineD3DSurface *)This)) + if (!surface_is_offscreen(This)) { - GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *)This); + GLenum buffer = surface_get_gl_buffer(This); TRACE("Locking %#x buffer\n", buffer); ENTER_GL(); @@ -1226,12 +1534,6 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) LEAVE_GL(); } - if(!(This->Flags & alloc_flag)) { - surface_allocate_surface(This, internal, This->pow2Width, - This->pow2Height, format, type); - This->Flags |= alloc_flag; - } - ENTER_GL(); /* If !SrcIsUpsideDown we should flip the surface. * This can be done using glCopyTexSubImage2D but this @@ -1254,34 +1556,47 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) } /* Context activation is done by the caller. */ -void surface_prepare_texture(IWineD3DSurfaceImpl *surface, BOOL srgb) +static void surface_prepare_texture_internal(IWineD3DSurfaceImpl *surface, + const struct wined3d_gl_info *gl_info, BOOL srgb) { DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED; - GLenum format, internal, type; - GLsizei width, height; CONVERT_TYPES convert; - int bpp; + struct wined3d_format_desc desc; if (surface->Flags & alloc_flag) return; - d3dfmt_get_conv(surface, TRUE, TRUE, &format, &internal, &type, &convert, &bpp, srgb); - if(convert != NO_CONVERSION) surface->Flags |= SFLAG_CONVERTED; + d3dfmt_get_conv(surface, TRUE, TRUE, &desc, &convert); + if(convert != NO_CONVERSION || desc.convert) surface->Flags |= SFLAG_CONVERTED; else surface->Flags &= ~SFLAG_CONVERTED; - if ((surface->Flags & SFLAG_NONPOW2) && !(surface->Flags & SFLAG_OVERSIZE)) - { - width = surface->pow2Width; - height = surface->pow2Height; - } - else + surface_bind_and_dirtify(surface, srgb); + surface_allocate_surface(surface, gl_info, &desc, srgb); + surface->Flags |= alloc_flag; +} + +/* Context activation is done by the caller. */ +void surface_prepare_texture(IWineD3DSurfaceImpl *surface, const struct wined3d_gl_info *gl_info, BOOL srgb) +{ + IWineD3DBaseTextureImpl *texture; + + if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)surface, + &IID_IWineD3DBaseTexture, (void **)&texture))) { - width = surface->glRect.right - surface->glRect.left; - height = surface->glRect.bottom - surface->glRect.top; + UINT sub_count = texture->baseTexture.level_count * texture->baseTexture.layer_count; + UINT i; + + TRACE("surface %p is a subresource of texture %p.\n", surface, texture); + + for (i = 0; i < sub_count; ++i) + { + IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[i]; + surface_prepare_texture_internal(s, gl_info, srgb); + } + + IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture); } - surface_bind_and_dirtify(surface, srgb); - surface_allocate_surface(surface, internal, width, height, format, type); - surface->Flags |= alloc_flag; + surface_prepare_texture_internal(surface, gl_info, srgb); } static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) @@ -1312,7 +1627,7 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) GLenum error; struct wined3d_context *context; - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); ENTER_GL(); GL_EXTCALL(glGenBuffersARB(1, &This->pbo)); @@ -1360,10 +1675,11 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; const RECT *pass_rect = pRect; - TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory); + TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n", + iface, pLockedRect, wine_dbgstr_rect(pRect), Flags); /* This is also done in the base class, but we have to verify this before loading any data from * gl into the sysmem copy. The PBO may be mapped, a different rectangle locked, the discard flag @@ -1404,7 +1720,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED } if (!(wined3d_settings.rendertargetlock_mode == RTL_DISABLE - && ((This->Flags & SFLAG_SWAPCHAIN) || iface == myDevice->render_targets[0]))) + && ((This->Flags & SFLAG_SWAPCHAIN) || This == device->render_targets[0]))) { IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pass_rect); } @@ -1412,9 +1728,12 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED lock_end: if (This->Flags & SFLAG_PBO) { + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; - context = context_acquire(myDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); + gl_info = context->gl_info; + ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); @@ -1443,7 +1762,7 @@ lock_end: * Dirtify on lock * as seen in msdn docs */ - surface_add_dirty_rect(iface, pRect); + surface_add_dirty_rect(This, pRect); /** Dirtify Container if needed */ if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture))) { @@ -1463,16 +1782,20 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm GLint prev_rasterpos[4]; GLint skipBytes = 0; UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */ - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; /* Activate the correct context for the render target */ - context = context_acquire(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); + context = context_acquire(device, This); + context_apply_blit_state(context, device); + gl_info = context->gl_info; + ENTER_GL(); - if (!surface_is_offscreen((IWineD3DSurface *)This)) + if (!surface_is_offscreen(This)) { - GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *)This); + GLenum buffer = surface_get_gl_buffer(This); TRACE("Unlocking %#x buffer.\n", buffer); context_set_draw_buffer(context, buffer); } @@ -1480,7 +1803,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm { /* Primary offscreen render target */ TRACE("Offscreen render target.\n"); - context_set_draw_buffer(context, myDevice->offscreenBuffer); + context_set_draw_buffer(context, device->offscreenBuffer); } glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store); @@ -1553,7 +1876,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; BOOL fullsurface; if (!(This->Flags & SFLAG_LOCKED)) { @@ -1563,11 +1886,14 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { if (This->Flags & SFLAG_PBO) { + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; TRACE("Freeing PBO memory\n"); - context = context_acquire(myDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); + gl_info = context->gl_info; + ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); @@ -1586,7 +1912,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { goto unlock_end; } - if ((This->Flags & SFLAG_SWAPCHAIN) || (myDevice->render_targets && iface == myDevice->render_targets[0])) + if ((This->Flags & SFLAG_SWAPCHAIN) || (device->render_targets && This == device->render_targets[0])) { if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) { static BOOL warned = FALSE; @@ -1633,7 +1959,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { This->dirtyRect.top = This->currentDesc.Height; This->dirtyRect.right = 0; This->dirtyRect.bottom = 0; - } else if(iface == myDevice->stencilBufferTarget) { + } + else if (This == device->depth_stencil) + { FIXME("Depth Stencil buffer locking is not implemented\n"); } else { /* The rest should be a normal texture */ @@ -1643,9 +1971,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { * states need resetting */ if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) { - if(impl->baseTexture.bindCount) { - IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler)); - } + if (impl->baseTexture.bindCount) + IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(impl->baseTexture.sampler)); IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl); } } @@ -1661,35 +1988,34 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { return WINED3D_OK; } -static void surface_release_client_storage(IWineD3DSurface *iface) +static void surface_release_client_storage(IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; struct wined3d_context *context; - context = context_acquire(This->resource.device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(surface->resource.device, NULL); ENTER_GL(); glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); - if(This->texture_name) + if (surface->texture_name) { - surface_bind_and_dirtify(This, FALSE); - glTexImage2D(This->texture_target, This->texture_level, - GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + surface_bind_and_dirtify(surface, FALSE); + glTexImage2D(surface->texture_target, surface->texture_level, + GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); } - if(This->texture_name_srgb) + if (surface->texture_name_srgb) { - surface_bind_and_dirtify(This, TRUE); - glTexImage2D(This->texture_target, This->texture_level, - GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + surface_bind_and_dirtify(surface, TRUE); + glTexImage2D(surface->texture_target, surface->texture_level, + GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); } glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); LEAVE_GL(); context_release(context); - IWineD3DSurface_ModifyLocation(iface, SFLAG_INSRGBTEX, FALSE); - IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); - surface_force_reload(iface); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INSRGBTEX, FALSE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INTEXTURE, FALSE); + surface_force_reload(surface); } static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) @@ -1720,7 +2046,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHD if(!This->hDC) { if(This->Flags & SFLAG_CLIENT) { IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); - surface_release_client_storage(iface); + surface_release_client_storage(This); } hr = IWineD3DBaseSurfaceImpl_CreateDIBSection(iface); if(FAILED(hr)) return WINED3DERR_INVALIDCALL; @@ -1761,7 +2087,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHD IWineD3DSurfaceImpl *dds_primary; IWineD3DSwapChainImpl *swapchain; swapchain = (IWineD3DSwapChainImpl *)This->resource.device->swapchains[0]; - dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer; + dds_primary = swapchain->front_buffer; if (dds_primary && dds_primary->palette) pal = dds_primary->palette->palents; } @@ -1815,28 +2141,17 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC IWineD3DSurface Internal (No mapping to directx api) parts follow ****************************************************** */ -HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode) { +HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, struct wined3d_format_desc *desc, CONVERT_TYPES *convert) +{ BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT); - const struct GlPixelFormatDesc *glDesc = This->resource.format_desc; IWineD3DDeviceImpl *device = This->resource.device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + BOOL blit_supported = FALSE; + RECT rect = {0, 0, This->pow2Width, This->pow2Height}; - /* Default values: From the surface */ - *format = glDesc->glFormat; - *type = glDesc->glType; + /* Copy the default values from the surface. Below we might perform fixups */ + /* TODO: get rid of color keying desc fixups by using e.g. a table. */ + *desc = *This->resource.format_desc; *convert = NO_CONVERSION; - *target_bpp = glDesc->byte_count; - - if(srgb_mode) { - *internal = glDesc->glGammaInternal; - } - else if (This->resource.usage & WINED3DUSAGE_RENDERTARGET - && surface_is_offscreen((IWineD3DSurface *) This)) - { - *internal = glDesc->rtInternal; - } else { - *internal = glDesc->glInternal; - } /* Ok, now look if we have to do any conversion */ switch(This->resource.format_desc->format) @@ -1846,34 +2161,30 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ Paletted Texture **************** */ - /* Use conversion when the paletted texture extension OR fragment shaders are available. When either - * of the two is available make sure texturing is requested as neither of the two works in - * conjunction with calls like glDraw-/glReadPixels. Further also use conversion in case of color keying. + blit_supported = device->blitter->blit_supported(&device->adapter->gl_info, BLIT_OP_BLIT, + &rect, This->resource.usage, This->resource.pool, + This->resource.format_desc, &rect, This->resource.usage, + This->resource.pool, This->resource.format_desc); + + /* Use conversion when the blit_shader backend supports it. It only supports this in case of + * texturing. Further also use conversion in case of color keying. * Paletted textures can be emulated using shaders but only do that for 2D purposes e.g. situations * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which * conflicts with this. */ - if (!(gl_info->supported[EXT_PALETTED_TEXTURE] || (device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup) - && device->render_targets && This == (IWineD3DSurfaceImpl*)device->render_targets[0])) + if (!((blit_supported && device->render_targets && This == device->render_targets[0])) || colorkey_active || !use_texturing) { - *format = GL_RGBA; - *internal = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - *target_bpp = 4; + desc->glFormat = GL_RGBA; + desc->glInternal = GL_RGBA; + desc->glType = GL_UNSIGNED_BYTE; + desc->conv_byte_count = 4; if(colorkey_active) { *convert = CONVERT_PALETTED_CK; } else { *convert = CONVERT_PALETTED; } } - else if (!gl_info->supported[EXT_PALETTED_TEXTURE] && device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup)) - { - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - *target_bpp = 1; - } - break; case WINED3DFMT_B2G3R3_UNORM: @@ -1890,149 +2201,40 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ case WINED3DFMT_B5G6R5_UNORM: if (colorkey_active) { *convert = CONVERT_CK_565; - *format = GL_RGBA; - *internal = GL_RGB5_A1; - *type = GL_UNSIGNED_SHORT_5_5_5_1; + desc->glFormat = GL_RGBA; + desc->glInternal = GL_RGB5_A1; + desc->glType = GL_UNSIGNED_SHORT_5_5_5_1; + desc->conv_byte_count = 2; } break; case WINED3DFMT_B5G5R5X1_UNORM: if (colorkey_active) { *convert = CONVERT_CK_5551; - *format = GL_BGRA; - *internal = GL_RGB5_A1; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + desc->glFormat = GL_BGRA; + desc->glInternal = GL_RGB5_A1; + desc->glType = GL_UNSIGNED_SHORT_1_5_5_5_REV; + desc->conv_byte_count = 2; } break; case WINED3DFMT_B8G8R8_UNORM: if (colorkey_active) { *convert = CONVERT_CK_RGB24; - *format = GL_RGBA; - *internal = GL_RGBA8; - *type = GL_UNSIGNED_INT_8_8_8_8; - *target_bpp = 4; + desc->glFormat = GL_RGBA; + desc->glInternal = GL_RGBA8; + desc->glType = GL_UNSIGNED_INT_8_8_8_8; + desc->conv_byte_count = 4; } break; case WINED3DFMT_B8G8R8X8_UNORM: if (colorkey_active) { *convert = CONVERT_RGB32_888; - *format = GL_RGBA; - *internal = GL_RGBA8; - *type = GL_UNSIGNED_INT_8_8_8_8; - } - break; - - case WINED3DFMT_R8G8_SNORM: - if (gl_info->supported[NV_TEXTURE_SHADER]) break; - *convert = CONVERT_V8U8; - *format = GL_BGR; - *type = GL_UNSIGNED_BYTE; - *target_bpp = 3; - break; - - case WINED3DFMT_R5G5_SNORM_L6_UNORM: - *convert = CONVERT_L6V5U5; - if (gl_info->supported[NV_TEXTURE_SHADER]) - { - *target_bpp = 3; - /* Use format and types from table */ - } else { - /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */ - *target_bpp = 2; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - } - break; - - case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: - *convert = CONVERT_X8L8V8U8; - *target_bpp = 4; - if (gl_info->supported[NV_TEXTURE_SHADER]) - { - /* Use formats from gl table. It is a bit unfortunate, but the conversion - * is needed to set the X format to 255 to get 1.0 for alpha when sampling - * the texture. OpenGL can't use GL_DSDT8_MAG8_NV as internal format with - * the needed type and format parameter, so the internal format contains a - * 4th component, which is returned as alpha - */ - } else { - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - } - break; - - case WINED3DFMT_R8G8B8A8_SNORM: - if (gl_info->supported[NV_TEXTURE_SHADER]) break; - *convert = CONVERT_Q8W8V8U8; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *target_bpp = 4; - break; - - case WINED3DFMT_R16G16_SNORM: - if (gl_info->supported[NV_TEXTURE_SHADER]) break; - *convert = CONVERT_V16U16; - *format = GL_BGR; - *type = GL_UNSIGNED_SHORT; - *target_bpp = 6; - break; - - case WINED3DFMT_L4A4_UNORM: - /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not - * format+type combination to load it. Thus convert it to A8L8, then load it - * with A4L4 internal, but A8L8 format+type - */ - *convert = CONVERT_A4L4; - *format = GL_LUMINANCE_ALPHA; - *type = GL_UNSIGNED_BYTE; - *target_bpp = 2; - break; - - case WINED3DFMT_R16G16_UNORM: - *convert = CONVERT_G16R16; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT; - *target_bpp = 6; - break; - - case WINED3DFMT_R16G16_FLOAT: - *convert = CONVERT_R16G16F; - *format = GL_RGB; - *type = GL_HALF_FLOAT_ARB; - *target_bpp = 6; - break; - - case WINED3DFMT_R32G32_FLOAT: - *convert = CONVERT_R32G32F; - *format = GL_RGB; - *type = GL_FLOAT; - *target_bpp = 12; - break; - - case WINED3DFMT_S1_UINT_D15_UNORM: - if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] - || gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) - { - *convert = CONVERT_D15S1; - *target_bpp = 4; - } - break; - - case WINED3DFMT_S4X4_UINT_D24_UNORM: - if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] - || gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) - { - *convert = CONVERT_D24X4S4; - } - break; - - case WINED3DFMT_S8_UINT_D24_FLOAT: - if (gl_info->supported[ARB_DEPTH_BUFFER_FLOAT]) - { - *convert = CONVERT_D24FS8; - *target_bpp = 8; + desc->glFormat = GL_RGBA; + desc->glInternal = GL_RGBA8; + desc->glType = GL_UNSIGNED_INT_8_8_8_8; + desc->conv_byte_count = 4; } break; @@ -2043,7 +2245,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ return WINED3D_OK; } -static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) +void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) { IWineD3DDeviceImpl *device = This->resource.device; IWineD3DPaletteImpl *pal = This->palette; @@ -2126,8 +2328,6 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This) { - IWineD3DDeviceImpl *device = This->resource.device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const BYTE *source; BYTE *dest; TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert,This); @@ -2273,338 +2473,12 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI } break; - case CONVERT_V8U8: - { - unsigned int x, y; - const short *Source; - unsigned char *Dest; - for(y = 0; y < height; y++) { - Source = (const short *)(src + y * pitch); - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - long color = (*Source++); - /* B */ Dest[0] = 0xff; - /* G */ Dest[1] = (color >> 8) + 128; /* V */ - /* R */ Dest[2] = (color) + 128; /* U */ - Dest += 3; - } - } - break; - } - - case CONVERT_V16U16: - { - unsigned int x, y; - const DWORD *Source; - unsigned short *Dest; - for(y = 0; y < height; y++) { - Source = (const DWORD *)(src + y * pitch); - Dest = (unsigned short *) (dst + y * outpitch); - for (x = 0; x < width; x++ ) { - DWORD color = (*Source++); - /* B */ Dest[0] = 0xffff; - /* G */ Dest[1] = (color >> 16) + 32768; /* V */ - /* R */ Dest[2] = (color ) + 32768; /* U */ - Dest += 3; - } - } - break; - } - - case CONVERT_Q8W8V8U8: - { - unsigned int x, y; - const DWORD *Source; - unsigned char *Dest; - for(y = 0; y < height; y++) { - Source = (const DWORD *)(src + y * pitch); - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - long color = (*Source++); - /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */ - /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */ - /* R */ Dest[2] = (color & 0xff) + 128; /* U */ - /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */ - Dest += 4; - } - } - break; - } - - case CONVERT_L6V5U5: - { - unsigned int x, y; - const WORD *Source; - unsigned char *Dest; - - if (gl_info->supported[NV_TEXTURE_SHADER]) - { - /* This makes the gl surface bigger(24 bit instead of 16), but it works with - * fixed function and shaders without further conversion once the surface is - * loaded - */ - for(y = 0; y < height; y++) { - Source = (const WORD *)(src + y * pitch); - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - short color = (*Source++); - unsigned char l = ((color >> 10) & 0xfc); - char v = ((color >> 5) & 0x3e); - char u = ((color ) & 0x1f); - - /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign - * and doubles the positive range. Thus shift left only once, gl does the 2nd - * shift. GL reads a signed value and converts it into an unsigned value. - */ - /* M */ Dest[2] = l << 1; - - /* Those are read as signed, but kept signed. Just left-shift 3 times to scale - * from 5 bit values to 8 bit values. - */ - /* V */ Dest[1] = v << 3; - /* U */ Dest[0] = u << 3; - Dest += 3; - } - } - } else { - for(y = 0; y < height; y++) { - unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch); - Source = (const WORD *)(src + y * pitch); - for (x = 0; x < width; x++ ) { - short color = (*Source++); - unsigned char l = ((color >> 10) & 0xfc); - short v = ((color >> 5) & 0x3e); - short u = ((color ) & 0x1f); - short v_conv = v + 16; - short u_conv = u + 16; - - *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f); - Dest_s += 1; - } - } - } - break; - } - - case CONVERT_X8L8V8U8: - { - unsigned int x, y; - const DWORD *Source; - unsigned char *Dest; - - if (gl_info->supported[NV_TEXTURE_SHADER]) - { - /* This implementation works with the fixed function pipeline and shaders - * without further modification after converting the surface. - */ - for(y = 0; y < height; y++) { - Source = (const DWORD *)(src + y * pitch); - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - long color = (*Source++); - /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */ - /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */ - /* U */ Dest[0] = (color & 0xff); /* U */ - /* I */ Dest[3] = 255; /* X */ - Dest += 4; - } - } - } else { - /* Doesn't work correctly with the fixed function pipeline, but can work in - * shaders if the shader is adjusted. (There's no use for this format in gl's - * standard fixed function pipeline anyway). - */ - for(y = 0; y < height; y++) { - Source = (const DWORD *)(src + y * pitch); - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - long color = (*Source++); - /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */ - /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */ - /* R */ Dest[2] = (color & 0xff) + 128; /* U */ - Dest += 4; - } - } - } - break; - } - - case CONVERT_A4L4: - { - unsigned int x, y; - const unsigned char *Source; - unsigned char *Dest; - for(y = 0; y < height; y++) { - Source = src + y * pitch; - Dest = dst + y * outpitch; - for (x = 0; x < width; x++ ) { - unsigned char color = (*Source++); - /* A */ Dest[1] = (color & 0xf0) << 0; - /* L */ Dest[0] = (color & 0x0f) << 4; - Dest += 2; - } - } - break; - } - - case CONVERT_G16R16: - case CONVERT_R16G16F: - { - unsigned int x, y; - const WORD *Source; - WORD *Dest; - - for(y = 0; y < height; y++) { - Source = (const WORD *)(src + y * pitch); - Dest = (WORD *) (dst + y * outpitch); - for (x = 0; x < width; x++ ) { - WORD green = (*Source++); - WORD red = (*Source++); - Dest[0] = green; - Dest[1] = red; - /* Strictly speaking not correct for R16G16F, but it doesn't matter because the - * shader overwrites it anyway - */ - Dest[2] = 0xffff; - Dest += 3; - } - } - break; - } - - case CONVERT_R32G32F: - { - unsigned int x, y; - const float *Source; - float *Dest; - for(y = 0; y < height; y++) { - Source = (const float *)(src + y * pitch); - Dest = (float *) (dst + y * outpitch); - for (x = 0; x < width; x++ ) { - float green = (*Source++); - float red = (*Source++); - Dest[0] = green; - Dest[1] = red; - Dest[2] = 1.0f; - Dest += 3; - } - } - break; - } - - case CONVERT_D15S1: - { - unsigned int x, y; - - for (y = 0; y < height; ++y) - { - const WORD *source = (const WORD *)(src + y * pitch); - DWORD *dest = (DWORD *)(dst + y * outpitch); - - for (x = 0; x < width; ++x) - { - /* The depth data is normalized, so needs to be scaled, - * the stencil data isn't. Scale depth data by - * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */ - WORD d15 = source[x] >> 1; - DWORD d24 = (d15 << 9) + (d15 >> 6); - dest[x] = (d24 << 8) | (source[x] & 0x1); - } - } - break; - } - - case CONVERT_D24X4S4: - { - unsigned int x, y; - - for (y = 0; y < height; ++y) - { - const DWORD *source = (const DWORD *)(src + y * pitch); - DWORD *dest = (DWORD *)(dst + y * outpitch); - - for (x = 0; x < width; ++x) - { - /* Just need to clear out the X4 part. */ - dest[x] = source[x] & ~0xf0; - } - } - break; - } - - case CONVERT_D24FS8: - { - unsigned int x, y; - - for (y = 0; y < height; ++y) - { - const DWORD *source = (const DWORD *)(src + y * pitch); - float *dest_f = (float *)(dst + y * outpitch); - DWORD *dest_s = (DWORD *)(dst + y * outpitch); - - for (x = 0; x < width; ++x) - { - dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8); - dest_s[x * 2 + 1] = source[x] & 0xff; - } - } - break; - } - default: ERR("Unsupported conversion type %#x.\n", convert); } return WINED3D_OK; } -/* This function is used in case of 8bit paletted textures to upload the palette. - It supports GL_EXT_paletted_texture and GL_ARB_fragment_program, support for other - extensions like ATI_fragment_shaders is possible. -*/ -/* Context activation is done by the caller. */ -static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - BYTE table[256][4]; - IWineD3DDeviceImpl *device = This->resource.device; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - - d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK)); - - /* Try to use the paletted texture extension */ - if (gl_info->supported[EXT_PALETTED_TEXTURE]) - { - TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n"); - ENTER_GL(); - GL_EXTCALL(glColorTableEXT(This->texture_target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table)); - LEAVE_GL(); - } - else - { - /* Let a fragment shader do the color conversion by uploading the palette to a 1D texture. - * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */ - TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n"); - - device->blitter->set_shader((IWineD3DDevice *) device, This->resource.format_desc, - This->texture_target, This->pow2Width, This->pow2Height); - - ENTER_GL(); - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1)); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Make sure we have discrete color levels. */ - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table); /* Upload the palette */ - - /* Switch back to unit 0 in which the 2D texture will be stored. */ - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0)); - - /* Rebind the texture because it isn't bound anymore */ - glBindTexture(This->texture_target, This->texture_name); - LEAVE_GL(); - } -} - BOOL palette9_changed(IWineD3DSurfaceImpl *This) { IWineD3DDeviceImpl *device = This->resource.device; @@ -2827,7 +2701,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, c LEAVE_GL(); } else { /* bind the real texture, and make sure it up to date */ - surface_internal_preload(iface, SRGB_RGB); + surface_internal_preload(This, SRGB_RGB); surface_bind_and_dirtify(This, FALSE); } allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4); @@ -2948,9 +2822,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *M IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); /* For client textures opengl has to be notified */ - if(This->Flags & SFLAG_CLIENT) { - surface_release_client_storage(iface); - } + if (This->Flags & SFLAG_CLIENT) + surface_release_client_storage(This); /* Now free the old memory if any */ HeapFree(GetProcessHeap(), 0, release); @@ -2961,9 +2834,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *M if(This->resource.heapMemory != NULL) ERR("User pointer surface has heap memory allocated\n"); This->Flags &= ~SFLAG_USERPTR; - if(This->Flags & SFLAG_CLIENT) { - surface_release_client_storage(iface); - } + if (This->Flags & SFLAG_CLIENT) + surface_release_client_storage(This); } return WINED3D_OK; } @@ -3099,7 +2971,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DS } /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */ - hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0); + hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *)swapchain, + NULL, NULL, swapchain->win_handle, NULL, 0); IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return hr; } @@ -3107,36 +2980,48 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DS /* Does a direct frame buffer -> texture copy. Stretching is done * with single pixel copy calls */ -static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, - const WINED3DRECT *srect, const WINED3DRECT *drect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) +static void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *dst_surface, IWineD3DSurfaceImpl *src_surface, + const RECT *src_rect, const RECT *dst_rect_in, WINED3DTEXTUREFILTERTYPE Filter) { - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = dst_surface->resource.device; float xrel, yrel; UINT row; - IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; struct wined3d_context *context; + BOOL upsidedown = FALSE; + RECT dst_rect = *dst_rect_in; + /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag + * glCopyTexSubImage is a bit picky about the parameters we pass to it + */ + if(dst_rect.top > dst_rect.bottom) { + UINT tmp = dst_rect.bottom; + dst_rect.bottom = dst_rect.top; + dst_rect.top = tmp; + upsidedown = TRUE; + } - context = context_acquire(myDevice, SrcSurface, CTXUSAGE_BLIT); - surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); + context = context_acquire(device, src_surface); + context_apply_blit_state(context, device); + surface_internal_preload(dst_surface, SRGB_RGB); ENTER_GL(); /* Bind the target texture */ - glBindTexture(This->texture_target, This->texture_name); + glBindTexture(dst_surface->texture_target, dst_surface->texture_name); checkGLcall("glBindTexture"); - if(surface_is_offscreen(SrcSurface)) { + if (surface_is_offscreen(src_surface)) + { TRACE("Reading from an offscreen target\n"); upsidedown = !upsidedown; - glReadBuffer(myDevice->offscreenBuffer); + glReadBuffer(device->offscreenBuffer); } else { - glReadBuffer(surface_get_gl_buffer(SrcSurface)); + glReadBuffer(surface_get_gl_buffer(src_surface)); } checkGLcall("glReadBuffer"); - xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1); - yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1); + xrel = (float) (src_rect->right - src_rect->left) / (float) (dst_rect.right - dst_rect.left); + yrel = (float) (src_rect->bottom - src_rect->top) / (float) (dst_rect.bottom - dst_rect.top); if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps)) { @@ -3158,19 +3043,19 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D { /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */ - glCopyTexSubImage2D(This->texture_target, This->texture_level, - drect->x1 /*xoffset */, drect->y1 /* y offset */, - srect->x1, Src->currentDesc.Height - srect->y2, - drect->x2 - drect->x1, drect->y2 - drect->y1); + glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level, + dst_rect.left /*xoffset */, dst_rect.top /* y offset */, + src_rect->left, src_surface->currentDesc.Height - src_rect->bottom, + dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top); } else { - UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1; + UINT yoffset = src_surface->currentDesc.Height - src_rect->top + dst_rect.top - 1; /* I have to process this row by row to swap the image, * otherwise it would be upside down, so stretching in y direction * doesn't cost extra time * * However, stretching in x direction can be avoided if not necessary */ - for(row = drect->y1; row < drect->y2; row++) { + for(row = dst_rect.top; row < dst_rect.bottom; row++) { if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps)) { /* Well, that stuff works, but it's very slow. @@ -3178,15 +3063,18 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D */ UINT col; - for(col = drect->x1; col < drect->x2; col++) { - glCopyTexSubImage2D(This->texture_target, This->texture_level, - drect->x1 + col /* x offset */, row /* y offset */, - srect->x1 + col * xrel, yoffset - (int) (row * yrel), 1, 1); + for (col = dst_rect.left; col < dst_rect.right; ++col) + { + glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level, + dst_rect.left + col /* x offset */, row /* y offset */, + src_rect->left + col * xrel, yoffset - (int) (row * yrel), 1, 1); } - } else { - glCopyTexSubImage2D(This->texture_target, This->texture_level, - drect->x1 /* x offset */, row /* y offset */, - srect->x1, yoffset - (int) (row * yrel), drect->x2-drect->x1, 1); + } + else + { + glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level, + dst_rect.left /* x offset */, row /* y offset */, + src_rect->left, yoffset - (int) (row * yrel), dst_rect.right - dst_rect.left, 1); } } } @@ -3198,37 +3086,39 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D /* The texture is now most up to date - If the surface is a render target and has a drawable, this * path is never entered */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INTEXTURE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INTEXTURE, TRUE); } /* Uses the hardware to stretch and flip the image */ -static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, - IWineD3DSwapChainImpl *swapchain, const WINED3DRECT *srect, const WINED3DRECT *drect, - BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) +static void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *dst_surface, IWineD3DSurfaceImpl *src_surface, + const RECT *src_rect, const RECT *dst_rect_in, WINED3DTEXTUREFILTERTYPE Filter) { - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = dst_surface->resource.device; GLuint src, backup = 0; - IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; + IWineD3DSwapChainImpl *src_swapchain = NULL; float left, right, top, bottom; /* Texture coordinates */ - UINT fbwidth = Src->currentDesc.Width; - UINT fbheight = Src->currentDesc.Height; + UINT fbwidth = src_surface->currentDesc.Width; + UINT fbheight = src_surface->currentDesc.Height; struct wined3d_context *context; GLenum drawBuffer = GL_BACK; GLenum texture_target; BOOL noBackBufferBackup; BOOL src_offscreen; + BOOL upsidedown = FALSE; + RECT dst_rect = *dst_rect_in; TRACE("Using hwstretch blit\n"); /* Activate the Proper context for reading from the source surface, set it up for blitting */ - context = context_acquire(myDevice, SrcSurface, CTXUSAGE_BLIT); - surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); + context = context_acquire(device, src_surface); + context_apply_blit_state(context, device); + surface_internal_preload(dst_surface, SRGB_RGB); - src_offscreen = surface_is_offscreen(SrcSurface); + src_offscreen = surface_is_offscreen(src_surface); noBackBufferBackup = src_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO; - if (!noBackBufferBackup && !Src->texture_name) + if (!noBackBufferBackup && !src_surface->texture_name) { /* Get it a description */ - surface_internal_preload(SrcSurface, SRGB_RGB); + surface_internal_preload(src_surface, SRGB_RGB); } ENTER_GL(); @@ -3240,7 +3130,7 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* Got more than one aux buffer? Use the 2nd aux buffer */ drawBuffer = GL_AUX1; } - else if ((!src_offscreen || myDevice->offscreenBuffer == GL_BACK) && context->aux_buffers >= 1) + else if ((!src_offscreen || device->offscreenBuffer == GL_BACK) && context->aux_buffers >= 1) { /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */ drawBuffer = GL_AUX0; @@ -3256,25 +3146,35 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If * we are reading from the back buffer, the backup can be used as source texture */ - texture_target = Src->texture_target; - glBindTexture(texture_target, Src->texture_name); - checkGLcall("glBindTexture(texture_target, Src->texture_name)"); + texture_target = src_surface->texture_target; + glBindTexture(texture_target, src_surface->texture_name); + checkGLcall("glBindTexture(texture_target, src_surface->texture_name)"); glEnable(texture_target); checkGLcall("glEnable(texture_target)"); /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */ - Src->Flags &= ~SFLAG_INTEXTURE; + src_surface->Flags &= ~SFLAG_INTEXTURE; + } + + /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag + * glCopyTexSubImage is a bit picky about the parameters we pass to it + */ + if(dst_rect.top > dst_rect.bottom) { + UINT tmp = dst_rect.bottom; + dst_rect.bottom = dst_rect.top; + dst_rect.top = tmp; + upsidedown = TRUE; } if (src_offscreen) { TRACE("Reading from an offscreen target\n"); upsidedown = !upsidedown; - glReadBuffer(myDevice->offscreenBuffer); + glReadBuffer(device->offscreenBuffer); } else { - glReadBuffer(surface_get_gl_buffer(SrcSurface)); + glReadBuffer(surface_get_gl_buffer(src_surface)); } /* TODO: Only back up the part that will be overwritten */ @@ -3294,9 +3194,14 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE)); checkGLcall("glTexParameteri"); - if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) { - src = backup ? backup : Src->texture_name; - } else { + IWineD3DSurface_GetContainer((IWineD3DSurface *)src_surface, &IID_IWineD3DSwapChain, (void **)&src_swapchain); + if (src_swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *)src_swapchain); + if (!src_swapchain || src_surface == src_swapchain->back_buffers[0]) + { + src = backup ? backup : src_surface->texture_name; + } + else + { glReadBuffer(GL_FRONT); checkGLcall("glReadBuffer(GL_FRONT)"); @@ -3305,11 +3210,11 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glBindTexture(GL_TEXTURE_2D, src); checkGLcall("glBindTexture(GL_TEXTURE_2D, src)"); - /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch + /* TODO: Only copy the part that will be read. Use src_rect->left, src_rect->bottom as origin, but with the width watch * out for power of 2 sizes */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_surface->pow2Width, + src_surface->pow2Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); checkGLcall("glTexImage2D"); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0 /* read offsets */, @@ -3333,22 +3238,26 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine } checkGLcall("glEnd and previous"); - left = srect->x1; - right = srect->x2; + left = src_rect->left; + right = src_rect->right; - if(upsidedown) { - top = Src->currentDesc.Height - srect->y1; - bottom = Src->currentDesc.Height - srect->y2; - } else { - top = Src->currentDesc.Height - srect->y2; - bottom = Src->currentDesc.Height - srect->y1; + if (upsidedown) + { + top = src_surface->currentDesc.Height - src_rect->top; + bottom = src_surface->currentDesc.Height - src_rect->bottom; + } + else + { + top = src_surface->currentDesc.Height - src_rect->bottom; + bottom = src_surface->currentDesc.Height - src_rect->top; } - if(Src->Flags & SFLAG_NORMCOORD) { - left /= Src->pow2Width; - right /= Src->pow2Width; - top /= Src->pow2Height; - bottom /= Src->pow2Height; + if (src_surface->Flags & SFLAG_NORMCOORD) + { + left /= src_surface->pow2Width; + right /= src_surface->pow2Width; + top /= src_surface->pow2Height; + bottom /= src_surface->pow2Height; } /* draw the source texture stretched and upside down. The correct surface is bound already */ @@ -3365,33 +3274,33 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* top left */ glTexCoord2f(left, top); - glVertex2i(0, fbheight - drect->y2 - drect->y1); + glVertex2i(0, fbheight - dst_rect.bottom - dst_rect.top); /* top right */ glTexCoord2f(right, top); - glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1); + glVertex2i(dst_rect.right - dst_rect.left, fbheight - dst_rect.bottom - dst_rect.top); /* bottom right */ glTexCoord2f(right, bottom); - glVertex2i(drect->x2 - drect->x1, fbheight); + glVertex2i(dst_rect.right - dst_rect.left, fbheight); glEnd(); checkGLcall("glEnd and previous"); - if (texture_target != This->texture_target) + if (texture_target != dst_surface->texture_target) { glDisable(texture_target); - glEnable(This->texture_target); - texture_target = This->texture_target; + glEnable(dst_surface->texture_target); + texture_target = dst_surface->texture_target; } /* Now read the stretched and upside down image into the destination texture */ - glBindTexture(texture_target, This->texture_name); + glBindTexture(texture_target, dst_surface->texture_name); checkGLcall("glBindTexture"); glCopyTexSubImage2D(texture_target, 0, - drect->x1, drect->y1, /* xoffset, yoffset */ + dst_rect.left, dst_rect.top, /* xoffset, yoffset */ 0, 0, /* We blitted the image to the origin */ - drect->x2 - drect->x1, drect->y2 - drect->y1); + dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top); checkGLcall("glCopyTexSubImage2D"); if(drawBuffer == GL_BACK) { @@ -3404,20 +3313,22 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine } glBindTexture(GL_TEXTURE_2D, backup); checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)"); - } else { - if (texture_target != Src->texture_target) - { - glDisable(texture_target); - glEnable(Src->texture_target); - texture_target = Src->texture_target; + } + else + { + if (texture_target != src_surface->texture_target) + { + glDisable(texture_target); + glEnable(src_surface->texture_target); + texture_target = src_surface->texture_target; } - glBindTexture(Src->texture_target, Src->texture_name); - checkGLcall("glBindTexture(Src->texture_target, Src->texture_name)"); + glBindTexture(src_surface->texture_target, src_surface->texture_name); + checkGLcall("glBindTexture(src_surface->texture_target, src_surface->texture_name)"); } glBegin(GL_QUADS); /* top left */ - glTexCoord2f(0.0f, (float)fbheight / (float)Src->pow2Height); + glTexCoord2f(0.0f, (float)fbheight / (float)src_surface->pow2Height); glVertex2i(0, 0); /* bottom left */ @@ -3425,11 +3336,12 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glVertex2i(0, fbheight); /* bottom right */ - glTexCoord2f((float)fbwidth / (float)Src->pow2Width, 0.0f); - glVertex2i(fbwidth, Src->currentDesc.Height); + glTexCoord2f((float)fbwidth / (float)src_surface->pow2Width, 0.0f); + glVertex2i(fbwidth, src_surface->currentDesc.Height); /* top right */ - glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height); + glTexCoord2f((float)fbwidth / (float)src_surface->pow2Width, + (float)fbheight / (float)src_surface->pow2Height); glVertex2i(fbwidth, 0); glEnd(); } @@ -3437,7 +3349,7 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine checkGLcall("glDisable(texture_target)"); /* Cleanup */ - if (src != Src->texture_name && src != backup) + if (src != src_surface->texture_name && src != backup) { glDeleteTextures(1, &src); checkGLcall("glDeleteTextures(1, &src)"); @@ -3449,48 +3361,76 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); /* The texture is now most up to date - If the surface is a render target and has a drawable, this * path is never entered */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INTEXTURE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INTEXTURE, TRUE); +} + +/* Until the blit_shader is ready, define some prototypes here. */ +static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, + const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, + const struct wined3d_format_desc *dst_format_desc); + +/* 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_frontbuffer_coords(IWineD3DSurfaceImpl *surface, HWND window, RECT *rect) +{ + POINT offset = {0, surface->currentDesc.Height}; + RECT windowsize; + + GetClientRect(window, &windowsize); + offset.y -= windowsize.bottom - windowsize.top; + ScreenToClient(window, &offset); + OffsetRect(rect, offset.x, offset.y); } /* Not called from the VTable */ -static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const RECT *DestRect, - IWineD3DSurface *SrcSurface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, +static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *dst_surface, const RECT *DestRect, + IWineD3DSurfaceImpl *src_surface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) { - IWineD3DDeviceImpl *myDevice = This->resource.device; - WINED3DRECT rect; + IWineD3DDeviceImpl *device = dst_surface->resource.device; IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL; - IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; + RECT dst_rect, src_rect; - TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx); + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, blt_fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(DestRect), src_surface, wine_dbgstr_rect(SrcRect), + Flags, DDBltFx, debug_d3dtexturefiltertype(Filter)); /* Get the swapchain. One of the surfaces has to be a primary surface */ - if(This->resource.pool == WINED3DPOOL_SYSTEMMEM) { + if (dst_surface->resource.pool == WINED3DPOOL_SYSTEMMEM) + { WARN("Destination is in sysmem, rejecting gl blt\n"); return WINED3DERR_INVALIDCALL; } - IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain); - if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain); - if(Src) { - if(Src->resource.pool == WINED3DPOOL_SYSTEMMEM) { + IWineD3DSurface_GetContainer((IWineD3DSurface *)dst_surface, &IID_IWineD3DSwapChain, (void **)&dstSwapchain); + if (dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *)dstSwapchain); + if (src_surface) + { + if (src_surface->resource.pool == WINED3DPOOL_SYSTEMMEM) + { WARN("Src is in sysmem, rejecting gl blt\n"); return WINED3DERR_INVALIDCALL; } - IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain); - if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain); + IWineD3DSurface_GetContainer((IWineD3DSurface *)src_surface, &IID_IWineD3DSwapChain, (void **)&srcSwapchain); + if (srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *)srcSwapchain); } /* Early sort out of cases where no render target is used */ - if(!dstSwapchain && !srcSwapchain && - SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) { - TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This); + if (!dstSwapchain && !srcSwapchain + && src_surface != device->render_targets[0] + && dst_surface != device->render_targets[0]) + { + TRACE("No surface is render target, not using hardware blit.\n"); return WINED3DERR_INVALIDCALL; } @@ -3501,21 +3441,14 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const return WINED3DERR_INVALIDCALL; } - if (DestRect) { - rect.x1 = DestRect->left; - rect.y1 = DestRect->top; - rect.x2 = DestRect->right; - rect.y2 = DestRect->bottom; - } else { - rect.x1 = 0; - rect.y1 = 0; - rect.x2 = This->currentDesc.Width; - rect.y2 = This->currentDesc.Height; - } + surface_get_rect(dst_surface, DestRect, &dst_rect); + if (src_surface) surface_get_rect(src_surface, SrcRect, &src_rect); /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */ - if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer && - ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) { + if (dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->back_buffers + && dst_surface == dstSwapchain->front_buffer + && src_surface == dstSwapchain->back_buffers[0]) + { /* Half-life does a Blt from the back buffer to the front buffer, * Full surface size, no flags... Use present instead * @@ -3525,57 +3458,50 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* Check rects - IWineD3DDevice_Present doesn't handle them */ while(1) { - RECT mySrcRect; TRACE("Looking if a Present can be done...\n"); /* Source Rectangle must be full surface */ - if( SrcRect ) { - if(SrcRect->left != 0 || SrcRect->top != 0 || - SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) { - TRACE("No, Source rectangle doesn't match\n"); - break; - } + if (src_rect.left || src_rect.top + || src_rect.right != src_surface->currentDesc.Width + || src_rect.bottom != src_surface->currentDesc.Height) + { + TRACE("No, Source rectangle doesn't match\n"); + break; } - mySrcRect.left = 0; - mySrcRect.top = 0; - mySrcRect.right = Src->currentDesc.Width; - mySrcRect.bottom = Src->currentDesc.Height; /* No stretching may occur */ - if(mySrcRect.right != rect.x2 - rect.x1 || - mySrcRect.bottom != rect.y2 - rect.y1) { + if(src_rect.right != dst_rect.right - dst_rect.left || + src_rect.bottom != dst_rect.bottom - dst_rect.top) { TRACE("No, stretching is done\n"); break; } /* Destination must be full surface or match the clipping rectangle */ - if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd) + if (dst_surface->clipper && ((IWineD3DClipperImpl *)dst_surface->clipper)->hWnd) { RECT cliprect; POINT pos[2]; - GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect); - pos[0].x = rect.x1; - pos[0].y = rect.y1; - pos[1].x = rect.x2; - pos[1].y = rect.y2; - MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd, - pos, 2); + GetClientRect(((IWineD3DClipperImpl *)dst_surface->clipper)->hWnd, &cliprect); + pos[0].x = dst_rect.left; + pos[0].y = dst_rect.top; + pos[1].x = dst_rect.right; + pos[1].y = dst_rect.bottom; + MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *)dst_surface->clipper)->hWnd, pos, 2); if(pos[0].x != cliprect.left || pos[0].y != cliprect.top || pos[1].x != cliprect.right || pos[1].y != cliprect.bottom) { TRACE("No, dest rectangle doesn't match(clipper)\n"); - TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom); - TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2); + TRACE("Clip rect at %s\n", wine_dbgstr_rect(&cliprect)); + TRACE("Blt dest: %s\n", wine_dbgstr_rect(&dst_rect)); break; } } - else + else if (dst_rect.left || dst_rect.top + || dst_rect.right != dst_surface->currentDesc.Width + || dst_rect.bottom != dst_surface->currentDesc.Height) { - if(rect.x1 != 0 || rect.y1 != 0 || - rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) { - TRACE("No, dest rectangle doesn't match(surface size)\n"); - break; - } + TRACE("No, dest rectangle doesn't match(surface size)\n"); + break; } TRACE("Yes\n"); @@ -3603,7 +3529,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const dstSwapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE; TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n"); - IWineD3DSwapChain_Present((IWineD3DSwapChain *) dstSwapchain, NULL, NULL, 0, NULL, 0); + IWineD3DSwapChain_Present((IWineD3DSwapChain *)dstSwapchain, + NULL, NULL, dstSwapchain->win_handle, NULL, 0); dstSwapchain->presentParms.SwapEffect = orig_swap; @@ -3620,21 +3547,31 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const } else if(dstSwapchain && srcSwapchain) { FIXME("Implement hardware blit between two different swapchains\n"); return WINED3DERR_INVALIDCALL; - } else if(dstSwapchain) { - if(SrcSurface == myDevice->render_targets[0]) { + } + else if (dstSwapchain) + { + /* Handled with regular texture -> swapchain blit */ + if (src_surface == device->render_targets[0]) TRACE("Blit from active render target to a swapchain\n"); - /* Handled with regular texture -> swapchain blit */ - } - } else if(srcSwapchain && This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) { + } + else if (srcSwapchain && dst_surface == device->render_targets[0]) + { FIXME("Implement blit from a swapchain to the active render target\n"); return WINED3DERR_INVALIDCALL; } - if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) { + if ((srcSwapchain || src_surface == device->render_targets[0]) && !dstSwapchain) + { /* Blit from render target to texture */ - WINED3DRECT srect; - BOOL upsideDown, stretchx; - BOOL paletteOverride = FALSE; + BOOL stretchx; + + /* P8 read back is not implemented */ + if (src_surface->resource.format_desc->format == WINED3DFMT_P8_UINT + || dst_surface->resource.format_desc->format == WINED3DFMT_P8_UINT) + { + TRACE("P8 read back not supported by frame buffer to texture blit\n"); + return WINED3DERR_INVALIDCALL; + } if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { TRACE("Color keying not supported by frame buffer to texture blit\n"); @@ -3642,50 +3579,12 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* Destination color key is checked above */ } - /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag - * glCopyTexSubImage is a bit picky about the parameters we pass to it - */ - if(SrcRect) { - if(SrcRect->top < SrcRect->bottom) { - srect.y1 = SrcRect->top; - srect.y2 = SrcRect->bottom; - upsideDown = FALSE; - } else { - srect.y1 = SrcRect->bottom; - srect.y2 = SrcRect->top; - upsideDown = TRUE; - } - srect.x1 = SrcRect->left; - srect.x2 = SrcRect->right; - } else { - srect.x1 = 0; - srect.y1 = 0; - srect.x2 = Src->currentDesc.Width; - srect.y2 = Src->currentDesc.Height; - upsideDown = FALSE; - } - if(rect.x1 > rect.x2) { - UINT tmp = rect.x2; - rect.x2 = rect.x1; - rect.x1 = tmp; - upsideDown = !upsideDown; - } - - if(rect.x2 - rect.x1 != srect.x2 - srect.x1) { + if(dst_rect.right - dst_rect.left != src_rect.right - src_rect.left) { stretchx = TRUE; } else { stretchx = FALSE; } - /* When blitting from a render target a texture, the texture isn't required to have a palette. - * In this case grab the palette from the render target. */ - if (This->resource.format_desc->format == WINED3DFMT_P8_UINT && !This->palette) - { - paletteOverride = TRUE; - TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This); - This->palette = Src->palette; - } - /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot * flip the image nor scale it. * @@ -3701,92 +3600,66 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering * backends. */ - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO - && myDevice->adapter->gl_info.fbo_ops.glBlitFramebuffer - && surface_can_stretch_rect(Src, This)) + if (fbo_blit_supported(&device->adapter->gl_info, BLIT_OP_BLIT, + &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format_desc, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format_desc)) + { + stretch_rect_fbo(device, src_surface, &src_rect, dst_surface, &dst_rect, Filter); + } + else if (!stretchx || dst_rect.right - dst_rect.left > src_surface->currentDesc.Width + || dst_rect.bottom - dst_rect.top > src_surface->currentDesc.Height) { - stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect, - (IWineD3DSurface *)This, &rect, Filter, upsideDown); - } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width || - rect.y2 - rect.y1 > Src->currentDesc.Height) { TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n"); - fb_copy_to_texture_direct(This, SrcSurface, &srect, &rect, upsideDown, 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(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter); + fb_copy_to_texture_hwstretch(dst_surface, src_surface, &src_rect, &dst_rect, Filter); } - /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */ - if(paletteOverride) - This->palette = NULL; - - if(!(This->Flags & SFLAG_DONOTFREE)) { - HeapFree(GetProcessHeap(), 0, This->resource.heapMemory); - This->resource.allocatedMemory = NULL; - This->resource.heapMemory = NULL; - } else { - This->Flags &= ~SFLAG_INSYSMEM; + if (!(dst_surface->Flags & SFLAG_DONOTFREE)) + { + HeapFree(GetProcessHeap(), 0, dst_surface->resource.heapMemory); + dst_surface->resource.allocatedMemory = NULL; + dst_surface->resource.heapMemory = NULL; + } + else + { + dst_surface->Flags &= ~SFLAG_INSYSMEM; } return WINED3D_OK; - } else if(Src) { + } + else if (src_surface) + { /* Blit from offscreen surface to render target */ - float glTexCoord[4]; - DWORD oldCKeyFlags = Src->CKeyFlags; - WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey; + DWORD oldCKeyFlags = src_surface->CKeyFlags; + WINEDDCOLORKEY oldBltCKey = src_surface->SrcBltCKey; struct wined3d_context *context; - RECT SourceRectangle; - BOOL paletteOverride = FALSE; - TRACE("Blt from surface %p to rendertarget %p\n", Src, This); + TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface); - if(SrcRect) { - SourceRectangle.left = SrcRect->left; - SourceRectangle.right = SrcRect->right; - SourceRectangle.top = SrcRect->top; - SourceRectangle.bottom = SrcRect->bottom; - } else { - SourceRectangle.left = 0; - SourceRectangle.right = Src->currentDesc.Width; - SourceRectangle.top = 0; - SourceRectangle.bottom = Src->currentDesc.Height; - } - - /* When blitting from an offscreen surface to a rendertarget, the source - * surface is not required to have a palette. Our rendering / conversion - * code further down the road retrieves the palette from the surface, so - * it must have a palette set. */ - if (Src->resource.format_desc->format == WINED3DFMT_P8_UINT && !Src->palette) - { - paletteOverride = TRUE; - TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This); - Src->palette = This->palette; - } - - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO - && myDevice->adapter->gl_info.fbo_ops.glBlitFramebuffer - && !(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) - && surface_can_stretch_rect(Src, This)) + if (!(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) + && fbo_blit_supported(&device->adapter->gl_info, BLIT_OP_BLIT, + &src_rect, src_surface->resource.usage, src_surface->resource.pool, + src_surface->resource.format_desc, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, + dst_surface->resource.format_desc)) { TRACE("Using stretch_rect_fbo\n"); /* The source is always a texture, but never the currently active render target, and the texture - * contents are never upside down - */ - stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, (WINED3DRECT *) &SourceRectangle, - (IWineD3DSurface *)This, &rect, Filter, FALSE); - - /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */ - if(paletteOverride) - Src->palette = NULL; + * contents are never upside down. */ + stretch_rect_fbo(device, src_surface, &src_rect, dst_surface, &dst_rect, Filter); return WINED3D_OK; } - if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) { - /* Fall back to software */ - WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src, - SourceRectangle.left, SourceRectangle.top, - SourceRectangle.right, SourceRectangle.bottom); - return WINED3DERR_INVALIDCALL; + if (!(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) + && arbfp_blit.blit_supported(&device->adapter->gl_info, BLIT_OP_BLIT, + &src_rect, src_surface->resource.usage, src_surface->resource.pool, + src_surface->resource.format_desc, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, + dst_surface->resource.format_desc)) + { + return arbfp_blit_surface(device, src_surface, &src_rect, dst_surface, &dst_rect, BLIT_OP_BLIT, Filter); } /* Color keying: Check if we have to do a color keyed blt, @@ -3800,72 +3673,35 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* Use color key from surface */ } else if(Flags & WINEDDBLT_KEYSRCOVERRIDE) { /* Use color key from DDBltFx */ - Src->CKeyFlags |= WINEDDSD_CKSRCBLT; - Src->SrcBltCKey = DDBltFx->ddckSrcColorkey; + src_surface->CKeyFlags |= WINEDDSD_CKSRCBLT; + src_surface->SrcBltCKey = DDBltFx->ddckSrcColorkey; } else { /* Do not use color key */ - Src->CKeyFlags &= ~WINEDDSD_CKSRCBLT; + src_surface->CKeyFlags &= ~WINEDDSD_CKSRCBLT; } /* Now load the surface */ - surface_internal_preload((IWineD3DSurface *) Src, SRGB_RGB); + surface_internal_preload(src_surface, SRGB_RGB); /* Activate the destination context, set it up for blitting */ - context = context_acquire(myDevice, (IWineD3DSurface *)This, CTXUSAGE_BLIT); + context = context_acquire(device, dst_surface); + context_apply_blit_state(context, device); - /* The coordinates of the ddraw front buffer are always fullscreen ('screen coordinates', - * while OpenGL coordinates are window relative. - * Also beware of the origin difference(top left vs bottom left). - * Also beware that the front buffer's surface size is screen width x screen height, - * whereas the real gl drawable size is the size of the window. - */ - if (dstSwapchain && (IWineD3DSurface *)This == dstSwapchain->frontBuffer) { - RECT windowsize; - POINT offset = {0,0}; - UINT h; - ClientToScreen(dstSwapchain->win_handle, &offset); - GetClientRect(dstSwapchain->win_handle, &windowsize); - h = windowsize.bottom - windowsize.top; - rect.x1 -= offset.x; rect.x2 -=offset.x; - rect.y1 -= offset.y; rect.y2 -=offset.y; - rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h; - } - - if (!is_identity_fixup(This->resource.format_desc->color_fixup)) - { - FIXME("Destination format %s has a fixup, this is not supported.\n", - debug_d3dformat(This->resource.format_desc->format)); - dump_color_fixup_desc(This->resource.format_desc->color_fixup); - } + if (dstSwapchain && dst_surface == dstSwapchain->front_buffer) + surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect); - if (!myDevice->blitter->color_fixup_supported(Src->resource.format_desc->color_fixup)) + if (!device->blitter->blit_supported(&device->adapter->gl_info, BLIT_OP_BLIT, + &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format_desc, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format_desc)) { - FIXME("Source format %s has an unsupported fixup:\n", - debug_d3dformat(Src->resource.format_desc->format)); - dump_color_fixup_desc(Src->resource.format_desc->color_fixup); + FIXME("Unsupported blit operation falling back to software\n"); + return WINED3DERR_INVALIDCALL; } - myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format_desc, - Src->texture_target, Src->pow2Width, Src->pow2Height); + device->blitter->set_shader((IWineD3DDevice *)device, src_surface); ENTER_GL(); - /* Bind the texture */ - glBindTexture(Src->texture_target, Src->texture_name); - checkGLcall("glBindTexture"); - - /* Filtering for StretchRect */ - glTexParameteri(Src->texture_target, GL_TEXTURE_MAG_FILTER, - wined3d_gl_mag_filter(magLookup, Filter)); - checkGLcall("glTexParameteri"); - glTexParameteri(Src->texture_target, GL_TEXTURE_MIN_FILTER, - wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE)); - checkGLcall("glTexParameteri"); - glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - checkGLcall("glTexEnvi"); - /* This is for color keying */ if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { glEnable(GL_ALPHA_TEST); @@ -3874,8 +3710,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* When the primary render target uses P8, the alpha component contains the palette index. * Which means that the colorkey is one of the palette entries. In other cases pixels that * should be masked away have alpha set to 0. */ - if(primary_render_target_is_p8(myDevice)) - glAlphaFunc(GL_NOTEQUAL, (float)Src->SrcBltCKey.dwColorSpaceLowValue / 256.0f); + if (primary_render_target_is_p8(device)) + glAlphaFunc(GL_NOTEQUAL, (float)src_surface->SrcBltCKey.dwColorSpaceLowValue / 256.0f); else glAlphaFunc(GL_NOTEQUAL, 0.0f); checkGLcall("glAlphaFunc"); @@ -3886,46 +3722,26 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* Draw a textured quad */ - glBegin(GL_QUADS); - - glColor3f(1.0f, 1.0f, 1.0f); - glTexCoord2f(glTexCoord[0], glTexCoord[2]); - glVertex3f(rect.x1, rect.y1, 0.0f); - - glTexCoord2f(glTexCoord[0], glTexCoord[3]); - glVertex3f(rect.x1, rect.y2, 0.0f); - - glTexCoord2f(glTexCoord[1], glTexCoord[3]); - glVertex3f(rect.x2, rect.y2, 0.0f); - - glTexCoord2f(glTexCoord[1], glTexCoord[2]); - glVertex3f(rect.x2, rect.y1, 0.0f); - - glEnd(); - checkGLcall("glEnd"); + draw_textured_quad(src_surface, &src_rect, &dst_rect, Filter); if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { glDisable(GL_ALPHA_TEST); checkGLcall("glDisable(GL_ALPHA_TEST)"); } - glBindTexture(Src->texture_target, 0); - checkGLcall("glBindTexture(Src->texture_target, 0)"); - /* Restore the color key parameters */ - Src->CKeyFlags = oldCKeyFlags; - Src->SrcBltCKey = oldBltCKey; - - /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */ - if(paletteOverride) - Src->palette = NULL; + src_surface->CKeyFlags = oldCKeyFlags; + src_surface->SrcBltCKey = oldBltCKey; LEAVE_GL(); /* Leave the opengl state valid for blitting */ - myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice); + device->blitter->unset_shader((IWineD3DDevice *)device); - wglFlush(); /* Flush to ensure ordering across contexts. */ + if (wined3d_settings.strict_draw_ordering || (dstSwapchain + && (dst_surface == dstSwapchain->front_buffer + || dstSwapchain->num_contexts > 1))) + wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); @@ -3933,74 +3749,40 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture * is outdated now */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INDRAWABLE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, TRUE); return WINED3D_OK; } else { /* Source-Less Blit to render target */ if (Flags & WINEDDBLT_COLORFILL) { - /* This is easy to handle for the D3D Device... */ DWORD color; TRACE("Colorfill\n"); - /* This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0] || dstSwapchain - must be true if we are here */ - if (This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0] && - !(This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer || - (dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]))) { - TRACE("Surface is higher back buffer, falling back to software\n"); - return WINED3DERR_INVALIDCALL; - } - /* The color as given in the Blt function is in the format of the frame-buffer... * 'clear' expect it in ARGB format => we need to do some conversion :-) */ - if (This->resource.format_desc->format == WINED3DFMT_P8_UINT) - { - DWORD alpha; - - if (primary_render_target_is_p8(myDevice)) alpha = DDBltFx->u5.dwFillColor << 24; - else alpha = 0xFF000000; - - if (This->palette) { - color = (alpha | - (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) | - (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) | - (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue)); - } else { - color = alpha; - } - } - else if (This->resource.format_desc->format == WINED3DFMT_B5G6R5_UNORM) + if (!surface_convert_color_to_argb(dst_surface, DDBltFx->u5.dwFillColor, &color)) { - if (DDBltFx->u5.dwFillColor == 0xFFFF) { - color = 0xFFFFFFFF; - } else { - color = ((0xFF000000) | - ((DDBltFx->u5.dwFillColor & 0xF800) << 8) | - ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) | - ((DDBltFx->u5.dwFillColor & 0x001F) << 3)); - } + /* The color conversion function already prints an error, so need to do it here */ + return WINED3DERR_INVALIDCALL; } - else if (This->resource.format_desc->format == WINED3DFMT_B8G8R8_UNORM - || This->resource.format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) + + if (ffp_blit.blit_supported(&device->adapter->gl_info, BLIT_OP_COLOR_FILL, + NULL, 0, 0, NULL, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, + dst_surface->resource.format_desc)) { - color = 0xFF000000 | DDBltFx->u5.dwFillColor; + return ffp_blit.color_fill(device, dst_surface, &dst_rect, color); } - else if (This->resource.format_desc->format == WINED3DFMT_B8G8R8A8_UNORM) + else if (cpu_blit.blit_supported(&device->adapter->gl_info, BLIT_OP_COLOR_FILL, + NULL, 0, 0, NULL, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, + dst_surface->resource.format_desc)) { - color = DDBltFx->u5.dwFillColor; + return cpu_blit.color_fill(device, dst_surface, &dst_rect, color); } - else { - ERR("Wrong surface type for BLT override(Format doesn't match) !\n"); - return WINED3DERR_INVALIDCALL; - } - - TRACE("(%p) executing Render Target override, color = %x\n", This, color); - IWineD3DDeviceImpl_ClearSurface(myDevice, This, 1 /* Number of rectangles */, - &rect, WINED3DCLEAR_TARGET, color, 0.0f /* Z */, 0 /* Stencil */); - return WINED3D_OK; + return WINED3DERR_INVALIDCALL; } } @@ -4012,7 +3794,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const static HRESULT IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, const RECT *DestRect, IWineD3DSurface *SrcSurface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx) { - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; float depth; if (Flags & WINEDDBLT_DEPTHFILL) { @@ -4036,13 +3818,8 @@ static HRESULT IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, const RECT *D ERR("Unexpected format for depth fill: %s\n", debug_d3dformat(This->resource.format_desc->format)); } - return IWineD3DDevice_Clear((IWineD3DDevice *) myDevice, - DestRect == NULL ? 0 : 1, - (const WINED3DRECT *)DestRect, - WINED3DCLEAR_ZBUFFER, - 0x00000000, - depth, - 0x00000000); + return IWineD3DDevice_Clear((IWineD3DDevice *)device, DestRect ? 1 : 0, (const WINED3DRECT *)DestRect, + WINED3DCLEAR_ZBUFFER, 0x00000000, depth, 0x00000000); } FIXME("(%p): Unsupp depthstencil blit\n", This); @@ -4053,7 +3830,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx); TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage)); @@ -4067,8 +3844,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair, * except depth blits, which seem to work */ - if(iface == myDevice->stencilBufferTarget || (SrcSurface && SrcSurface == myDevice->stencilBufferTarget)) { - if(myDevice->inScene && !(Flags & WINEDDBLT_DEPTHFILL)) { + if (This == device->depth_stencil || (Src && Src == device->depth_stencil)) + { + if (device->inScene && !(Flags & WINEDDBLT_DEPTHFILL)) + { TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n"); return WINED3DERR_INVALIDCALL; } else if(IWineD3DSurfaceImpl_BltZ(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) { @@ -4078,9 +3857,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT } /* Special cases for RenderTargets */ - if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) || - ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) { - if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK) return WINED3D_OK; + if ((This->resource.usage & WINED3DUSAGE_RENDERTARGET) + || (Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET))) + { + if (SUCCEEDED(IWineD3DSurfaceImpl_BltOverride(This, DestRect, Src, SrcRect, Flags, DDBltFx, Filter))) + return WINED3D_OK; } /* For the rest call the X11 surface implementation. @@ -4095,7 +3876,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source; - IWineD3DDeviceImpl *myDevice = This->resource.device; + IWineD3DDeviceImpl *device = This->resource.device; TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans); @@ -4105,9 +3886,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD return WINEDDERR_SURFACEBUSY; } - if(myDevice->inScene && - (iface == myDevice->stencilBufferTarget || - (Source == myDevice->stencilBufferTarget))) { + if (device->inScene && (This == device->depth_stencil || srcImpl == device->depth_stencil)) + { TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n"); return WINED3DERR_INVALIDCALL; } @@ -4119,17 +3899,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD RECT SrcRect, DstRect; DWORD Flags=0; - if(rsrc) { - SrcRect.left = rsrc->left; - SrcRect.top= rsrc->top; - SrcRect.bottom = rsrc->bottom; - SrcRect.right = rsrc->right; - } else { - SrcRect.left = 0; - SrcRect.top = 0; - SrcRect.right = srcImpl->currentDesc.Width; - SrcRect.bottom = srcImpl->currentDesc.Height; - } + surface_get_rect(srcImpl, rsrc, &SrcRect); DstRect.left = dstx; DstRect.top=dsty; @@ -4146,7 +3916,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD if(trans & WINEDDBLTFAST_DONOTWAIT) Flags |= WINEDDBLT_DONOTWAIT; - if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL, WINED3DTEXF_POINT) == WINED3D_OK) return WINED3D_OK; + if (SUCCEEDED(IWineD3DSurfaceImpl_BltOverride(This, + &DstRect, srcImpl, &SrcRect, Flags, NULL, WINED3DTEXF_POINT))) + return WINED3D_OK; } @@ -4166,31 +3938,13 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) if (This->resource.format_desc->format == WINED3DFMT_P8_UINT || This->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) { - int bpp; - GLenum format, internal, type; - CONVERT_TYPES convert; - - /* Check if we are using a RTL mode which uses texturing for uploads */ - BOOL use_texture = (wined3d_settings.rendertargetlock_mode == RTL_READTEX); - - /* Check if we have hardware palette conversion if we have convert is set to NO_CONVERSION */ - d3dfmt_get_conv(This, TRUE, use_texture, &format, &internal, &type, &convert, &bpp, FALSE); - - if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION)) + if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { - IWineD3DDeviceImpl *device = This->resource.device; - struct wined3d_context *context; - /* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */ IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL); /* We want to force a palette refresh, so mark the drawable as not being up to date */ IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); - - /* Re-upload the palette */ - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); - d3dfmt_p8_upload_palette(iface, convert); - context_release(context); } else { if(!(This->Flags & SFLAG_INSYSMEM)) { TRACE("Palette changed with surface that does not have an up to date system memory copy\n"); @@ -4269,18 +4023,18 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { 3: WARN and return WINED3DERR_NOTAVAILABLE; 4: Create the surface, but allow it to be used only for DirectDraw Blts. Some apps(e.g. Swat 3) create textures with a Height of 16 and a Width > 3000 and blt 16x16 letter areas from them to the render target. */ - WARN("(%p) Creating an oversized surface: %ux%u (texture is %ux%u)\n", - This, This->pow2Width, This->pow2Height, This->currentDesc.Width, This->currentDesc.Height); - This->Flags |= SFLAG_OVERSIZE; - - /* This will be initialized on the first blt */ - This->glRect.left = 0; - This->glRect.top = 0; - This->glRect.right = 0; - This->glRect.bottom = 0; - } else { - /* Check this after the oversize check - do not make an oversized surface a texture_rectangle one. - Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE + if(This->resource.pool == WINED3DPOOL_DEFAULT || This->resource.pool == WINED3DPOOL_MANAGED) + { + WARN("(%p) Unable to allocate a surface which exceeds the maximum OpenGL texture size\n", This); + return WINED3DERR_NOTAVAILABLE; + } + + /* We should never use this surface in combination with OpenGL! */ + TRACE("(%p) Creating an oversized surface: %ux%u\n", This, This->pow2Width, This->pow2Height); + } + else + { + /* Don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE doesn't work in combination with ARB_TEXTURE_RECTANGLE. */ @@ -4294,19 +4048,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { This->pow2Height = This->currentDesc.Height; This->Flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD); } - - /* No oversize, gl rect is the full texture size */ - This->Flags &= ~SFLAG_OVERSIZE; - This->glRect.left = 0; - This->glRect.top = 0; - This->glRect.right = This->pow2Width; - This->glRect.bottom = This->pow2Height; } if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { switch(wined3d_settings.offscreen_rendering_mode) { case ORM_FBO: This->get_drawable_size = get_drawable_size_fbo; break; - case ORM_PBUFFER: This->get_drawable_size = get_drawable_size_pbuffer; break; case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break; } } @@ -4316,104 +4062,13 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { return WINED3D_OK; } -struct depth_blt_info -{ - GLenum binding; - GLenum bind_target; - enum tex_types tex_type; - GLfloat coords[4][3]; -}; - -static void surface_get_depth_blt_info(GLenum target, GLsizei w, GLsizei h, struct depth_blt_info *info) -{ - GLfloat (*coords)[3] = info->coords; - - 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 = tex_2d; - coords[0][0] = 0.0f; coords[0][1] = 1.0f; coords[0][2] = 0.0f; - coords[1][0] = 1.0f; coords[1][1] = 1.0f; coords[1][2] = 0.0f; - coords[2][0] = 0.0f; coords[2][1] = 0.0f; coords[2][2] = 0.0f; - coords[3][0] = 1.0f; coords[3][1] = 0.0f; coords[3][2] = 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 = tex_rect; - coords[0][0] = 0.0f; coords[0][1] = h; coords[0][2] = 0.0f; - coords[1][0] = w; coords[1][1] = h; coords[1][2] = 0.0f; - coords[2][0] = 0.0f; coords[2][1] = 0.0f; coords[2][2] = 0.0f; - coords[3][0] = w; coords[3][1] = 0.0f; coords[3][2] = 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 = tex_cube; - coords[0][0] = 1.0f; coords[0][1] = -1.0f; coords[0][2] = 1.0f; - coords[1][0] = 1.0f; coords[1][1] = -1.0f; coords[1][2] = -1.0f; - coords[2][0] = 1.0f; coords[2][1] = 1.0f; coords[2][2] = 1.0f; - coords[3][0] = 1.0f; coords[3][1] = 1.0f; coords[3][2] = -1.0f; - - 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 = tex_cube; - coords[0][0] = -1.0f; coords[0][1] = -1.0f; coords[0][2] = -1.0f; - coords[1][0] = -1.0f; coords[1][1] = -1.0f; coords[1][2] = 1.0f; - coords[2][0] = -1.0f; coords[2][1] = 1.0f; coords[2][2] = -1.0f; - coords[3][0] = -1.0f; coords[3][1] = 1.0f; coords[3][2] = 1.0f; - - 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 = tex_cube; - coords[0][0] = -1.0f; coords[0][1] = 1.0f; coords[0][2] = 1.0f; - coords[1][0] = 1.0f; coords[1][1] = 1.0f; coords[1][2] = 1.0f; - coords[2][0] = -1.0f; coords[2][1] = 1.0f; coords[2][2] = -1.0f; - coords[3][0] = 1.0f; coords[3][1] = 1.0f; coords[3][2] = -1.0f; - - 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 = tex_cube; - coords[0][0] = -1.0f; coords[0][1] = -1.0f; coords[0][2] = -1.0f; - coords[1][0] = 1.0f; coords[1][1] = -1.0f; coords[1][2] = -1.0f; - coords[2][0] = -1.0f; coords[2][1] = -1.0f; coords[2][2] = 1.0f; - coords[3][0] = 1.0f; coords[3][1] = -1.0f; coords[3][2] = 1.0f; - - 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 = tex_cube; - coords[0][0] = -1.0f; coords[0][1] = -1.0f; coords[0][2] = 1.0f; - coords[1][0] = 1.0f; coords[1][1] = -1.0f; coords[1][2] = 1.0f; - coords[2][0] = -1.0f; coords[2][1] = 1.0f; coords[2][2] = 1.0f; - coords[3][0] = 1.0f; coords[3][1] = 1.0f; coords[3][2] = 1.0f; - - 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 = tex_cube; - coords[0][0] = 1.0f; coords[0][1] = -1.0f; coords[0][2] = -1.0f; - coords[1][0] = -1.0f; coords[1][1] = -1.0f; coords[1][2] = -1.0f; - coords[2][0] = 1.0f; coords[2][1] = 1.0f; coords[2][2] = -1.0f; - coords[3][0] = -1.0f; coords[3][1] = 1.0f; coords[3][2] = -1.0f; - } -} - /* GL locking is done by the caller */ -static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei w, GLsizei h, GLenum target) +static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl_info *gl_info, + GLuint texture, GLsizei w, GLsizei h, GLenum target) { IWineD3DDeviceImpl *device = This->resource.device; - struct depth_blt_info info; + GLint compare_mode = GL_NONE; + struct blt_info info; GLint old_binding = 0; glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT); @@ -4429,12 +4084,18 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glViewport(0, 0, w, h); - surface_get_depth_blt_info(target, w, h, &info); + surface_get_blt_info(target, NULL, w, h, &info); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); glGetIntegerv(info.binding, &old_binding); glBindTexture(info.bind_target, texture); + if (gl_info->supported[ARB_SHADOW]) + { + glGetTexParameteriv(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, &compare_mode); + if (compare_mode != GL_NONE) glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + } - device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, info.tex_type); + device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, + info.tex_type, &This->ds_current_size); glBegin(GL_TRIANGLE_STRIP); glTexCoord3fv(info.coords[0]); @@ -4447,6 +4108,7 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei glVertex2f(1.0f, 1.0f); glEnd(); + if (compare_mode != GL_NONE) glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, compare_mode); glBindTexture(info.bind_target, old_binding); glPopAttrib(); @@ -4454,139 +4116,156 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei device->shader_backend->shader_deselect_depth_blt((IWineD3DDevice *)device); } -void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - - TRACE("(%p) New location %#x\n", This, location); +void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, + DWORD location, UINT w, UINT h) +{ + TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h); - if (location & ~SFLAG_DS_LOCATIONS) { - FIXME("(%p) Invalid location (%#x) specified\n", This, location); - } + if (location & ~SFLAG_DS_LOCATIONS) + FIXME("Invalid location (%#x) specified.\n", location); - This->Flags &= ~SFLAG_DS_LOCATIONS; - This->Flags |= location; + surface->ds_current_size.cx = w; + surface->ds_current_size.cy = h; + surface->Flags &= ~SFLAG_DS_LOCATIONS; + surface->Flags |= location; } /* Context activation is done by the caller. */ -void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location) +void surface_load_ds_location(IWineD3DSurfaceImpl *surface, struct wined3d_context *context, DWORD location) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.device; + IWineD3DDeviceImpl *device = surface->resource.device; const struct wined3d_gl_info *gl_info = context->gl_info; - TRACE("(%p) New location %#x\n", This, location); + TRACE("surface %p, new location %#x.\n", surface, location); /* TODO: Make this work for modes other than FBO */ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return; - if (This->Flags & location) { - TRACE("(%p) Location (%#x) is already up to date\n", This, location); - return; + if (!(surface->Flags & location)) + { + surface->ds_current_size.cx = 0; + surface->ds_current_size.cy = 0; } - if (This->current_renderbuffer) { - FIXME("(%p) Not supported with fixed up depth stencil\n", This); + if (surface->ds_current_size.cx == surface->currentDesc.Width + && surface->ds_current_size.cy == surface->currentDesc.Height) + { + TRACE("Location (%#x) is already up to date.\n", location); return; } - if (location == SFLAG_DS_OFFSCREEN) { - if (This->Flags & SFLAG_DS_ONSCREEN) { - GLint old_binding = 0; - GLenum bind_target; - - TRACE("(%p) Copying onscreen depth buffer to depth texture\n", This); - - ENTER_GL(); - - if (!device->depth_blt_texture) { - glGenTextures(1, &device->depth_blt_texture); - } + if (surface->current_renderbuffer) + { + FIXME("Not supported with fixed up depth stencil.\n"); + return; + } - /* Note that we use depth_blt here as well, rather than glCopyTexImage2D - * directly on the FBO texture. That's because we need to flip. */ - context_bind_fbo(context, GL_FRAMEBUFFER, NULL); - if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) - { - glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); - bind_target = GL_TEXTURE_RECTANGLE_ARB; - } else { - glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); - bind_target = GL_TEXTURE_2D; - } - glBindTexture(bind_target, device->depth_blt_texture); - glCopyTexImage2D(bind_target, This->texture_level, This->resource.format_desc->glInternal, - 0, 0, This->currentDesc.Width, This->currentDesc.Height, 0); - glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); - glBindTexture(bind_target, old_binding); - - /* Setup the destination */ - if (!device->depth_blt_rb) { - gl_info->fbo_ops.glGenRenderbuffers(1, &device->depth_blt_rb); - checkGLcall("glGenRenderbuffersEXT"); - } - if (device->depth_blt_rb_w != This->currentDesc.Width - || device->depth_blt_rb_h != This->currentDesc.Height) { - gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, device->depth_blt_rb); - checkGLcall("glBindRenderbufferEXT"); - gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, - This->currentDesc.Width, This->currentDesc.Height); - checkGLcall("glRenderbufferStorageEXT"); - device->depth_blt_rb_w = This->currentDesc.Width; - device->depth_blt_rb_h = This->currentDesc.Height; - } + if (!(surface->Flags & SFLAG_LOCATIONS)) + { + FIXME("No up to date depth stencil location.\n"); + surface->Flags |= location; + return; + } - context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo); - gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, device->depth_blt_rb); - checkGLcall("glFramebufferRenderbufferEXT"); - context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, iface, FALSE); + if (location == SFLAG_DS_OFFSCREEN) + { + GLint old_binding = 0; + GLenum bind_target; - /* Do the actual blit */ - surface_depth_blt(This, device->depth_blt_texture, This->currentDesc.Width, This->currentDesc.Height, bind_target); - checkGLcall("depth_blt"); + TRACE("Copying onscreen depth buffer to depth texture.\n"); - if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER, &context->current_fbo->id); - else context_bind_fbo(context, GL_FRAMEBUFFER, NULL); + ENTER_GL(); - LEAVE_GL(); + if (!device->depth_blt_texture) + { + glGenTextures(1, &device->depth_blt_texture); + } - wglFlush(); /* Flush to ensure ordering across contexts. */ + /* Note that we use depth_blt here as well, rather than glCopyTexImage2D + * directly on the FBO texture. That's because we need to flip. */ + context_bind_fbo(context, GL_FRAMEBUFFER, NULL); + if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB) + { + glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); + bind_target = GL_TEXTURE_RECTANGLE_ARB; } else { - FIXME("No up to date depth stencil location\n"); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); + bind_target = GL_TEXTURE_2D; + } + glBindTexture(bind_target, device->depth_blt_texture); + glCopyTexImage2D(bind_target, surface->texture_level, surface->resource.format_desc->glInternal, + 0, 0, surface->currentDesc.Width, surface->currentDesc.Height, 0); + glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); + glBindTexture(bind_target, old_binding); + + /* Setup the destination */ + if (!device->depth_blt_rb) + { + gl_info->fbo_ops.glGenRenderbuffers(1, &device->depth_blt_rb); + checkGLcall("glGenRenderbuffersEXT"); + } + if (device->depth_blt_rb_w != surface->currentDesc.Width + || device->depth_blt_rb_h != surface->currentDesc.Height) + { + gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, device->depth_blt_rb); + checkGLcall("glBindRenderbufferEXT"); + gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, + surface->currentDesc.Width, surface->currentDesc.Height); + checkGLcall("glRenderbufferStorageEXT"); + device->depth_blt_rb_w = surface->currentDesc.Width; + device->depth_blt_rb_h = surface->currentDesc.Height; } - } else if (location == SFLAG_DS_ONSCREEN) { - if (This->Flags & SFLAG_DS_OFFSCREEN) { - TRACE("(%p) Copying depth texture to onscreen depth buffer\n", This); - ENTER_GL(); + context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo); + gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, device->depth_blt_rb); + checkGLcall("glFramebufferRenderbufferEXT"); + context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, surface, FALSE); - context_bind_fbo(context, GL_FRAMEBUFFER, NULL); - surface_depth_blt(This, This->texture_name, This->currentDesc.Width, - This->currentDesc.Height, This->texture_target); - checkGLcall("depth_blt"); + /* Do the actual blit */ + surface_depth_blt(surface, gl_info, device->depth_blt_texture, + surface->currentDesc.Width, surface->currentDesc.Height, bind_target); + checkGLcall("depth_blt"); - if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER, &context->current_fbo->id); + if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER, &context->current_fbo->id); + else context_bind_fbo(context, GL_FRAMEBUFFER, NULL); - LEAVE_GL(); + LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ - } - else - { - FIXME("No up to date depth stencil location\n"); - } - } else { - ERR("(%p) Invalid location (%#x) specified\n", This, location); + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ } + else if (location == SFLAG_DS_ONSCREEN) + { + TRACE("Copying depth texture to onscreen depth buffer.\n"); + + ENTER_GL(); + + context_bind_fbo(context, GL_FRAMEBUFFER, NULL); + surface_depth_blt(surface, gl_info, surface->texture_name, + surface->currentDesc.Width, surface->currentDesc.Height, surface->texture_target); + checkGLcall("depth_blt"); + + if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER, &context->current_fbo->id); + + LEAVE_GL(); - This->Flags |= location; + if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */ + } + else + { + ERR("Invalid location (%#x) specified.\n", location); + } + + surface->Flags |= location; + surface->ds_current_size.cx = surface->currentDesc.Width; + surface->ds_current_size.cy = surface->currentDesc.Height; } static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) { @@ -4597,8 +4276,9 @@ static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DW TRACE("(%p)->(%s, %s)\n", iface, debug_surflocation(flag), persistent ? "TRUE" : "FALSE"); - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - if (surface_is_offscreen(iface)) + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + if (surface_is_offscreen(This)) { /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */ if (flag & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) flag |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE); @@ -4643,185 +4323,44 @@ static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DW } } -struct coords { - GLfloat x, y, z; -}; - -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 inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) { IWineD3DDeviceImpl *device = This->resource.device; - IWineD3DBaseTextureImpl *texture; + IWineD3DSwapChainImpl *swapchain; struct wined3d_context *context; - struct coords coords[4]; - RECT rect; - GLenum bind_target; - struct float_rect f; + RECT src_rect, dst_rect; - if(rect_in) { - rect = *rect_in; - } else { - rect.left = 0; - rect.top = 0; - rect.right = This->currentDesc.Width; - rect.bottom = This->currentDesc.Height; - } + surface_get_rect(This, rect_in, &src_rect); - switch (This->texture_target) + context = context_acquire(device, This); + context_apply_blit_state(context, device); + if (context->render_offscreen) { - case GL_TEXTURE_2D: - bind_target = GL_TEXTURE_2D; - - coords[0].x = (float)rect.left / This->pow2Width; - coords[0].y = (float)rect.top / This->pow2Height; - coords[0].z = 0; - - coords[1].x = (float)rect.left / This->pow2Width; - coords[1].y = (float)rect.bottom / This->pow2Height; - coords[1].z = 0; - - coords[2].x = (float)rect.right / This->pow2Width; - coords[2].y = (float)rect.bottom / This->pow2Height; - coords[2].z = 0; - - coords[3].x = (float)rect.right / This->pow2Width; - coords[3].y = (float)rect.top / This->pow2Height; - coords[3].z = 0; - break; - - case GL_TEXTURE_RECTANGLE_ARB: - bind_target = GL_TEXTURE_RECTANGLE_ARB; - coords[0].x = rect.left; coords[0].y = rect.top; coords[0].z = 0; - coords[1].x = rect.left; coords[1].y = rect.bottom; coords[1].z = 0; - coords[2].x = rect.right; coords[2].y = rect.bottom; coords[2].z = 0; - coords[3].x = rect.right; coords[3].y = rect.top; coords[3].z = 0; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = 1; coords[0].y = -f.t; coords[0].z = -f.l; - coords[1].x = 1; coords[1].y = -f.b; coords[1].z = -f.l; - coords[2].x = 1; coords[2].y = -f.b; coords[2].z = -f.r; - coords[3].x = 1; coords[3].y = -f.t; coords[3].z = -f.r; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = -1; coords[0].y = -f.t; coords[0].z = f.l; - coords[1].x = -1; coords[1].y = -f.b; coords[1].z = f.l; - coords[2].x = -1; coords[2].y = -f.b; coords[2].z = f.r; - coords[3].x = -1; coords[3].y = -f.t; coords[3].z = f.r; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = f.l; coords[0].y = 1; coords[0].z = f.t; - coords[1].x = f.l; coords[1].y = 1; coords[1].z = f.b; - coords[2].x = f.r; coords[2].y = 1; coords[2].z = f.b; - coords[3].x = f.r; coords[3].y = 1; coords[3].z = f.t; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = f.l; coords[0].y = -1; coords[0].z = -f.t; - coords[1].x = f.l; coords[1].y = -1; coords[1].z = -f.b; - coords[2].x = f.r; coords[2].y = -1; coords[2].z = -f.b; - coords[3].x = f.r; coords[3].y = -1; coords[3].z = -f.t; - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = f.l; coords[0].y = -f.t; coords[0].z = 1; - coords[1].x = f.l; coords[1].y = -f.b; coords[1].z = 1; - coords[2].x = f.r; coords[2].y = -f.b; coords[2].z = 1; - coords[3].x = f.r; coords[3].y = -f.t; coords[3].z = 1; - break; - - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - bind_target = GL_TEXTURE_CUBE_MAP_ARB; - cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f); - coords[0].x = -f.l; coords[0].y = -f.t; coords[0].z = -1; - coords[1].x = -f.l; coords[1].y = -f.b; coords[1].z = -1; - coords[2].x = -f.r; coords[2].y = -f.b; coords[2].z = -1; - coords[3].x = -f.r; coords[3].y = -f.t; coords[3].z = -1; - break; - - default: - ERR("Unexpected texture target %#x\n", This->texture_target); - return; + dst_rect.left = src_rect.left; + dst_rect.right = src_rect.right; + dst_rect.top = src_rect.bottom; + dst_rect.bottom = src_rect.top; } - - context = context_acquire(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); - - ENTER_GL(); - - glEnable(bind_target); - checkGLcall("glEnable(bind_target)"); - glBindTexture(bind_target, This->texture_name); - checkGLcall("glBindTexture(bind_target, This->texture_name)"); - glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - checkGLcall("glTexParameteri"); - glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - checkGLcall("glTexParameteri"); - - if (context->render_offscreen) + else { - LONG tmp = rect.top; - rect.top = rect.bottom; - rect.bottom = tmp; + dst_rect = src_rect; } - glBegin(GL_QUADS); - glTexCoord3fv(&coords[0].x); - glVertex2i(rect.left, rect.top); - - glTexCoord3fv(&coords[1].x); - glVertex2i(rect.left, rect.bottom); - - glTexCoord3fv(&coords[2].x); - glVertex2i(rect.right, rect.bottom); - - glTexCoord3fv(&coords[3].x); - glVertex2i(rect.right, rect.top); - glEnd(); - checkGLcall("glEnd"); + if ((This->Flags & SFLAG_SWAPCHAIN) && This == ((IWineD3DSwapChainImpl *)This->container)->front_buffer) + surface_translate_frontbuffer_coords(This, context->win_handle, &dst_rect); - glDisable(bind_target); - checkGLcall("glDisable(bind_target)"); + device->blitter->set_shader((IWineD3DDevice *) device, This); + ENTER_GL(); + draw_textured_quad(This, &src_rect, &dst_rect, WINED3DTEXF_POINT); LEAVE_GL(); - wglFlush(); /* Flush to ensure ordering across contexts. */ + device->blitter->set_shader((IWineD3DDevice *) device, This); - /* We changed the filtering settings on the texture. Inform the - * container about this to get the filters reset properly next draw. */ - if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)This, &IID_IWineD3DBaseTexture, (void **)&texture))) - { - texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; - texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; - texture->baseTexture.texture_rgb.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE; - IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture); - } + swapchain = (This->Flags & SFLAG_SWAPCHAIN) ? (IWineD3DSwapChainImpl *)This->container : NULL; + if (wined3d_settings.strict_draw_ordering || (swapchain + && (This == swapchain->front_buffer || swapchain->num_contexts > 1))) + wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); } @@ -4851,16 +4390,32 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DDeviceImpl *device = This->resource.device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - GLenum format, internal, type; + struct wined3d_format_desc desc; CONVERT_TYPES convert; - int bpp; int width, pitch, outpitch; BYTE *mem; BOOL drawable_read_ok = TRUE; BOOL in_fbo = FALSE; - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - if (surface_is_offscreen(iface)) + if (This->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) + { + if (flag == SFLAG_INTEXTURE) + { + struct wined3d_context *context = context_acquire(device, NULL); + surface_load_ds_location(This, context, SFLAG_DS_OFFSCREEN); + context_release(context); + return WINED3D_OK; + } + else + { + FIXME("Unimplemented location %#x for depth/stencil buffers.\n", flag); + return WINED3DERR_INVALIDCALL; + } + } + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + if (surface_is_offscreen(This)) { /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. * Prefer SFLAG_INTEXTURE. */ @@ -4898,10 +4453,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D { struct wined3d_context *context = NULL; - if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) context = context_acquire(device, NULL); surface_bind_and_dirtify(This, !(This->Flags & SFLAG_INTEXTURE)); - surface_download_data(This); + surface_download_data(This, gl_info); if (context) context_release(context); } @@ -4916,6 +4471,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D if(This->Flags & SFLAG_INTEXTURE) { surface_blt_to_drawable(This, rect); } else { + int byte_count; if((This->Flags & SFLAG_LOCATIONS) == SFLAG_INSRGBTEX) { /* This needs a shader to convert the srgb data sampled from the GL texture into RGB * values, otherwise we get incorrect values in the target. For now go the slow way @@ -4924,7 +4480,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D IWineD3DSurfaceImpl_LoadLocation(iface, SFLAG_INSYSMEM, rect); } - d3dfmt_get_conv(This, TRUE /* We need color keying */, FALSE /* We won't use textures */, &format, &internal, &type, &convert, &bpp, FALSE); + d3dfmt_get_conv(This, FALSE /* We need color keying */, FALSE /* We won't use textures */, &desc, &convert); /* The width is in 'length' not in bytes */ width = This->currentDesc.Width; @@ -4938,16 +4494,17 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D TRACE("Removing the pbo attached to surface %p\n", This); - if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); - surface_remove_pbo(This); + if (!device->isInDraw) context = context_acquire(device, NULL); + surface_remove_pbo(This, gl_info); if (context) context_release(context); } if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { int height = This->currentDesc.Height; + byte_count = desc.conv_byte_count; /* Stick to the alignment for the converted surface too, makes it easier to load the surface */ - outpitch = width * bpp; + outpitch = width * byte_count; outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1); mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height); @@ -4961,9 +4518,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D } else { This->Flags &= ~SFLAG_CONVERTED; mem = This->resource.allocatedMemory; + byte_count = desc.byte_count; } - flush_to_framebuffer_drawpixels(This, format, type, bpp, mem); + flush_to_framebuffer_drawpixels(This, desc.glFormat, desc.glType, byte_count, mem); /* Don't delete PBO memory */ if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO)) @@ -4980,7 +4538,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D struct wined3d_context *context = NULL; d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, - &format, &internal, &type, &convert, &bpp, srgb); + &desc, &convert); if(srgb) { if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)) == SFLAG_INTEXTURE) { @@ -5002,9 +4560,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D IWineD3DSurfaceImpl_LoadLocation(iface, SFLAG_INSYSMEM, rect); } - if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) context = context_acquire(device, NULL); - surface_prepare_texture(This, srgb); + surface_prepare_texture(This, gl_info, srgb); surface_bind_and_dirtify(This, srgb); if(This->CKeyFlags & WINEDDSD_CKSRCBLT) { @@ -5019,16 +4577,32 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED * but it isn't set (yet) in all cases it is getting called. */ - if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) { + if(((convert != NO_CONVERSION) || desc.convert) && (This->Flags & SFLAG_PBO)) { TRACE("Removing the pbo attached to surface %p\n", This); - surface_remove_pbo(This); + surface_remove_pbo(This, gl_info); } - if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { + if(desc.convert) { + /* This code is entered for texture formats which need a fixup. */ int height = This->currentDesc.Height; /* Stick to the alignment for the converted surface too, makes it easier to load the surface */ - outpitch = width * bpp; + outpitch = width * desc.conv_byte_count; + outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1); + + mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height); + if(!mem) { + ERR("Out of memory %d, %d!\n", outpitch, height); + if (context) context_release(context); + return WINED3DERR_OUTOFVIDEOMEMORY; + } + desc.convert(This->resource.allocatedMemory, mem, pitch, width, height); + } else if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { + /* This code is only entered for color keying fixups */ + int height = This->currentDesc.Height; + + /* Stick to the alignment for the converted surface too, makes it easier to load the surface */ + outpitch = width * desc.conv_byte_count; outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1); mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height); @@ -5038,12 +4612,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D return WINED3DERR_OUTOFVIDEOMEMORY; } d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This); - } - else if (This->resource.format_desc->format == WINED3DFMT_P8_UINT - && (gl_info->supported[EXT_PALETTED_TEXTURE] || device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup))) - { - d3dfmt_p8_upload_palette(iface, convert); - mem = This->resource.allocatedMemory; } else { mem = This->resource.allocatedMemory; } @@ -5053,19 +4621,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D glPixelStorei(GL_UNPACK_ROW_LENGTH, width); LEAVE_GL(); - if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) { - TRACE("non power of two support\n"); - if (mem || (This->Flags & SFLAG_PBO)) { - surface_upload_data(This, internal, This->currentDesc.Width, This->currentDesc.Height, format, type, mem); - } - } else { - /* When making the realloc conditional, keep in mind that GL_APPLE_client_storage may be in use, and This->resource.allocatedMemory - * changed. So also keep track of memory changes. In this case the texture has to be reallocated - */ - if (mem || (This->Flags & SFLAG_PBO)) { - surface_upload_data(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem); - } - } + if (mem || (This->Flags & SFLAG_PBO)) + surface_upload_data(This, gl_info, &desc, srgb, mem); /* Restore the default pitch */ ENTER_GL(); @@ -5107,7 +4664,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, I } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { switch(wined3d_settings.offscreen_rendering_mode) { case ORM_FBO: This->get_drawable_size = get_drawable_size_fbo; break; - case ORM_PBUFFER: This->get_drawable_size = get_drawable_size_pbuffer; break; case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break; } } @@ -5141,16 +4697,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_DrawOverlay(IWineD3DSurface *iface) { return hr; } -BOOL surface_is_offscreen(IWineD3DSurface *iface) +BOOL surface_is_offscreen(IWineD3DSurfaceImpl *surface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) This->container; + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)surface->container; /* Not on a swapchain - must be offscreen */ - if (!(This->Flags & SFLAG_SWAPCHAIN)) return TRUE; + if (!(surface->Flags & SFLAG_SWAPCHAIN)) return TRUE; /* The front buffer is always onscreen */ - if(iface == swapchain->frontBuffer) return FALSE; + if (surface == swapchain->front_buffer) return FALSE; /* If the swapchain is rendered to an FBO, the backbuffer is * offscreen, otherwise onscreen */ @@ -5212,20 +4767,42 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_GetImplType, IWineD3DSurfaceImpl_DrawOverlay }; -#undef GLINFO_LOCATION -#define GLINFO_LOCATION device->adapter->gl_info static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } /* Context activation is done by the caller. */ static void ffp_blit_free(IWineD3DDevice *iface) { } +/* This function is used in case of 8bit paletted textures using GL_EXT_paletted_texture */ +/* Context activation is done by the caller. */ +static void ffp_blit_p8_upload_palette(IWineD3DSurfaceImpl *surface, const struct wined3d_gl_info *gl_info) +{ + BYTE table[256][4]; + BOOL colorkey_active = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) ? TRUE : FALSE; + + d3dfmt_p8_init_palette(surface, table, colorkey_active); + + TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n"); + ENTER_GL(); + GL_EXTCALL(glColorTableEXT(surface->texture_target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table)); + LEAVE_GL(); +} + /* Context activation is done by the caller. */ -static HRESULT ffp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatDesc *format_desc, - GLenum textype, UINT width, UINT height) +static HRESULT ffp_blit_set(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + enum complex_fixup fixup = get_complex_fixup(surface->resource.format_desc->color_fixup); + + /* When EXT_PALETTED_TEXTURE is around, palette conversion is done by the GPU + * else the surface is converted in software at upload time in LoadLocation. + */ + if(fixup == COMPLEX_FIXUP_P8 && gl_info->supported[EXT_PALETTED_TEXTURE]) + ffp_blit_p8_upload_palette(surface, gl_info); + ENTER_GL(); - glEnable(textype); - checkGLcall("glEnable(textype)"); + glEnable(surface->texture_target); + checkGLcall("glEnable(surface->texture_target)"); LEAVE_GL(); return WINED3D_OK; } @@ -5252,16 +4829,52 @@ static void ffp_blit_unset(IWineD3DDevice *iface) LEAVE_GL(); } -static BOOL ffp_blit_color_fixup_supported(struct color_fixup_desc fixup) +static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, + const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, + const struct wined3d_format_desc *dst_format_desc) { + enum complex_fixup src_fixup; + + if (blit_op == BLIT_OP_COLOR_FILL) + { + if (!(dst_usage & WINED3DUSAGE_RENDERTARGET)) + { + TRACE("Color fill not supported\n"); + return FALSE; + } + + return TRUE; + } + + src_fixup = get_complex_fixup(src_format_desc->color_fixup); if (TRACE_ON(d3d_surface) && TRACE_ON(d3d)) { TRACE("Checking support for fixup:\n"); - dump_color_fixup_desc(fixup); + dump_color_fixup_desc(src_format_desc->color_fixup); + } + + if (blit_op != BLIT_OP_BLIT) + { + TRACE("Unsupported blit_op=%d\n", blit_op); + return FALSE; + } + + if (!is_identity_fixup(dst_format_desc->color_fixup)) + { + TRACE("Destination fixups are not supported\n"); + return FALSE; + } + + if (src_fixup == COMPLEX_FIXUP_P8 && gl_info->supported[EXT_PALETTED_TEXTURE]) + { + TRACE("P8 fixup supported\n"); + return TRUE; } /* We only support identity conversions. */ - if (is_identity_fixup(fixup)) + if (is_identity_fixup(src_format_desc->color_fixup)) { TRACE("[OK]\n"); return TRUE; @@ -5271,10 +4884,105 @@ static BOOL ffp_blit_color_fixup_supported(struct color_fixup_desc fixup) return FALSE; } +static HRESULT ffp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color) +{ + return IWineD3DDeviceImpl_ClearSurface(device, dst_surface, 1 /* Number of rectangles */, + (const WINED3DRECT*)dst_rect, WINED3DCLEAR_TARGET, fill_color, 0.0f /* Z */, 0 /* Stencil */); +} + const struct blit_shader ffp_blit = { ffp_blit_alloc, ffp_blit_free, ffp_blit_set, ffp_blit_unset, - ffp_blit_color_fixup_supported + ffp_blit_supported, + ffp_blit_color_fill }; + +static HRESULT cpu_blit_alloc(IWineD3DDevice *iface) +{ + return WINED3D_OK; +} + +/* Context activation is done by the caller. */ +static void cpu_blit_free(IWineD3DDevice *iface) +{ +} + +/* Context activation is done by the caller. */ +static HRESULT cpu_blit_set(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface) +{ + return WINED3D_OK; +} + +/* Context activation is done by the caller. */ +static void cpu_blit_unset(IWineD3DDevice *iface) +{ +} + +static BOOL cpu_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, + const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, + const struct wined3d_format_desc *dst_format_desc) +{ + if (blit_op == BLIT_OP_COLOR_FILL) + { + return TRUE; + } + + return FALSE; +} + +static HRESULT cpu_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color) +{ + WINEDDBLTFX BltFx; + memset(&BltFx, 0, sizeof(BltFx)); + BltFx.dwSize = sizeof(BltFx); + BltFx.u5.dwFillColor = color_convert_argb_to_fmt(fill_color, dst_surface->resource.format_desc->format); + return IWineD3DBaseSurfaceImpl_Blt((IWineD3DSurface*)dst_surface, dst_rect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); +} + +const struct blit_shader cpu_blit = { + cpu_blit_alloc, + cpu_blit_free, + cpu_blit_set, + cpu_blit_unset, + cpu_blit_supported, + cpu_blit_color_fill +}; + +static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, + const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, + const struct wined3d_format_desc *dst_format_desc) +{ + if ((wined3d_settings.offscreen_rendering_mode != ORM_FBO) || !gl_info->fbo_ops.glBlitFramebuffer) + return FALSE; + + /* We only support blitting. Things like color keying / color fill should + * be handled by other blitters. + */ + if (blit_op != BLIT_OP_BLIT) + return FALSE; + + /* Source and/or destination need to be on the GL side */ + if (src_pool == WINED3DPOOL_SYSTEMMEM || dst_pool == WINED3DPOOL_SYSTEMMEM) + return FALSE; + + if(!((src_format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (src_usage & WINED3DUSAGE_RENDERTARGET)) + && ((dst_format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (dst_usage & WINED3DUSAGE_RENDERTARGET))) + return FALSE; + + if (!is_identity_fixup(src_format_desc->color_fixup) || + !is_identity_fixup(dst_format_desc->color_fixup)) + return FALSE; + + if (!(src_format_desc->format == dst_format_desc->format + || (is_identity_fixup(src_format_desc->color_fixup) + && is_identity_fixup(dst_format_desc->color_fixup)))) + return FALSE; + + return TRUE; +} diff --git a/reactos/dll/directx/wine/wined3d/surface_base.c b/reactos/dll/directx/wine/wined3d/surface_base.c index 33e3d3ed885..2b6cdb41f22 100644 --- a/reactos/dll/directx/wine/wined3d/surface_base.c +++ b/reactos/dll/directx/wine/wined3d/surface_base.c @@ -83,9 +83,6 @@ static inline unsigned short float_32_to_16(const float *in) return ret; } - -/* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */ - /* ******************************************* IWineD3DSurface IUnknown parts follow ******************************************* */ @@ -326,7 +323,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; + const struct wined3d_format_desc *format_desc = This->resource.format_desc; DWORD ret; TRACE("(%p)\n", This); @@ -502,7 +499,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWin HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, &This->resource.device->adapter->gl_info); if (This->resource.format_desc->format != WINED3DFMT_UNKNOWN) @@ -527,7 +524,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3D HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; + const struct wined3d_format_desc *format_desc = This->resource.format_desc; int extraline = 0; SYSTEM_INFO sysInfo; BITMAPINFO* b_info; @@ -742,6 +739,55 @@ static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst, } } +static inline BYTE cliptobyte(int x) +{ + return (BYTE) ((x < 0) ? 0 : ((x > 255) ? 255 : x)); +} + +static void convert_yuy2_x8r8g8b8(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + unsigned int x, y; + int c2, d, e, r2 = 0, g2 = 0, b2 = 0; + + TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const BYTE *src_line = src + y * pitch_in; + DWORD *dst_line = (DWORD *)(dst + y * pitch_out); + for (x = 0; x < w; ++x) + { + /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV: + * C = Y - 16; D = U - 128; E = V - 128; + * R = cliptobyte((298 * C + 409 * E + 128) >> 8); + * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8); + * B = cliptobyte((298 * C + 516 * D + 128) >> 8); + * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V . + * U and V are shared between the pixels. + */ + if (!(x & 1)) /* for every even pixel, read new U and V */ + { + d = (int) src_line[1] - 128; + e = (int) src_line[3] - 128; + r2 = 409 * e + 128; + g2 = - 100 * d - 208 * e + 128; + b2 = 516 * d + 128; + } + c2 = 298 * ((int) src_line[0] - 16); + dst_line[x] = 0xff000000 + | cliptobyte((c2 + r2) >> 8) << 16 /* red */ + | cliptobyte((c2 + g2) >> 8) << 8 /* green */ + | cliptobyte((c2 + b2) >> 8); /* blue */ + /* Scale RGB values to 0..255 range, + * then clip them if still not in range (may be negative), + * then shift them within DWORD if necessary. + */ + src_line += 2; + } + } +} + struct d3dfmt_convertor_desc { WINED3DFORMAT from, to; void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h); @@ -752,6 +798,7 @@ static const struct d3dfmt_convertor_desc convertors[] = {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float}, {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8}, {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8}, + {WINED3DFMT_YUY2, WINED3DFMT_B8G8R8X8_UNORM, convert_yuy2_x8r8g8b8}, }; static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to) @@ -892,7 +939,7 @@ static HRESULT /***************************************************************************** * IWineD3DSurface::Blt, SW emulation version * - * Performs blits to a surface, eigher from a source of source-less blts + * Performs a blit to a surface, with or without a source surface. * This is the main functionality of DirectDraw * * Params: @@ -909,7 +956,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *D HRESULT ret = WINED3D_OK; WINED3DLOCKED_RECT dlock, slock; int bpp, srcheight, srcwidth, dstheight, dstwidth, width; - const struct GlPixelFormatDesc *sEntry, *dEntry; + const struct wined3d_format_desc *sEntry, *dEntry; int x, y; const BYTE *sbuf; BYTE *dbuf; @@ -943,145 +990,146 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *D FIXME("Filters not supported in software blit\n"); } - /* First check for the validity of source / destination rectangles. This was - * verified using a test application + by MSDN. - */ - if ((Src != NULL) && (SrcRect != NULL) && - ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) || - (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) || - (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) || - (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) || - (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top))) - { - WARN("Application gave us bad source rectangle for Blt.\n"); - return WINEDDERR_INVALIDRECT; - } - /* For the Destination rect, it can be out of bounds on the condition that a clipper - * is set for the given surface. - */ - if ((/*This->clipper == NULL*/ TRUE) && (DestRect) && - ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) || - (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) || - (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) || - (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) || - (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top))) + /* First check for the validity of source / destination rectangles. + * This was verified using a test application + by MSDN. */ + + if (SrcRect) { - WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); - return WINEDDERR_INVALIDRECT; - } + if (Src) + { + if (SrcRect->right < SrcRect->left || SrcRect->bottom < SrcRect->top + || SrcRect->left > Src->currentDesc.Width || SrcRect->left < 0 + || SrcRect->top > Src->currentDesc.Height || SrcRect->top < 0 + || SrcRect->right > Src->currentDesc.Width || SrcRect->right < 0 + || SrcRect->bottom > Src->currentDesc.Height || SrcRect->bottom < 0) + { + WARN("Application gave us bad source rectangle for Blt.\n"); + return WINEDDERR_INVALIDRECT; + } - /* Now handle negative values in the rectangles. Warning: only supported for now - in the 'simple' cases (ie not in any stretching / rotation cases). + if (!SrcRect->right || !SrcRect->bottom + || SrcRect->left == (int)Src->currentDesc.Width + || SrcRect->top == (int)Src->currentDesc.Height) + { + TRACE("Nothing to be done.\n"); + return WINED3D_OK; + } + } - First, the case where nothing is to be done. - */ - if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) || - (DestRect->top >= (int) This->currentDesc.Height) || - (DestRect->left >= (int) This->currentDesc.Width))) || - ((Src != NULL) && (SrcRect != NULL) && - ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) || - (SrcRect->top >= (int) Src->currentDesc.Height) || - (SrcRect->left >= (int) Src->currentDesc.Width)) )) - { - TRACE("Nothing to be done !\n"); - return WINED3D_OK; + xsrc = *SrcRect; } - - if (DestRect) + else if (Src) { - xdst = *DestRect; + xsrc.left = 0; + xsrc.top = 0; + xsrc.right = Src->currentDesc.Width; + xsrc.bottom = Src->currentDesc.Height; } else { - xdst.top = 0; - xdst.bottom = This->currentDesc.Height; - xdst.left = 0; - xdst.right = This->currentDesc.Width; + memset(&xsrc, 0, sizeof(xsrc)); } - if (SrcRect) - { - xsrc = *SrcRect; - } - else + if (DestRect) { - if (Src) + /* For the Destination rect, it can be out of bounds on the condition + * that a clipper is set for the given surface. */ + if (!This->clipper && (DestRect->right < DestRect->left || DestRect->bottom < DestRect->top + || DestRect->left > This->currentDesc.Width || DestRect->left < 0 + || DestRect->top > This->currentDesc.Height || DestRect->top < 0 + || DestRect->right > This->currentDesc.Width || DestRect->right < 0 + || DestRect->bottom > This->currentDesc.Height || DestRect->bottom < 0)) { - xsrc.top = 0; - xsrc.bottom = Src->currentDesc.Height; - xsrc.left = 0; - xsrc.right = Src->currentDesc.Width; + WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); + return WINEDDERR_INVALIDRECT; } - else + + if (DestRect->right <= 0 || DestRect->bottom <= 0 + || DestRect->left >= (int)This->currentDesc.Width + || DestRect->top >= (int)This->currentDesc.Height) { - memset(&xsrc,0,sizeof(xsrc)); + TRACE("Nothing to be done.\n"); + return WINED3D_OK; } - } - /* The easy case : the source-less blits.... */ - if (Src == NULL && DestRect) - { - RECT full_rect; - RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */ + if (!Src) + { + RECT full_rect; - full_rect.left = 0; - full_rect.top = 0; - full_rect.right = This->currentDesc.Width; - full_rect.bottom = This->currentDesc.Height; - IntersectRect(&temp_rect, &full_rect, DestRect); - xdst = temp_rect; - } - else if (DestRect) - { - /* Only handle clipping on the destination rectangle */ - int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width ); - int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height); - if (clip_vert || clip_horiz) + full_rect.left = 0; + full_rect.top = 0; + full_rect.right = This->currentDesc.Width; + full_rect.bottom = This->currentDesc.Height; + IntersectRect(&xdst, &full_rect, DestRect); + } + else { - /* Now check if this is a special case or not... */ - if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || - (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) || - (Flags & WINEDDBLT_DDFX)) - { - WARN("Out of screen rectangle in special case. Not handled right now.\n"); - return WINED3D_OK; - } + BOOL clip_horiz, clip_vert; - if (clip_horiz) + xdst = *DestRect; + clip_horiz = xdst.left < 0 || xdst.right > (int)This->currentDesc.Width; + clip_vert = xdst.top < 0 || xdst.bottom > (int)This->currentDesc.Height; + + if (clip_vert || clip_horiz) { - if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; } - if (DestRect->right > This->currentDesc.Width) + /* Now check if this is a special case or not... */ + if ((Flags & WINEDDBLT_DDFX) + || (clip_horiz && xdst.right - xdst.left != xsrc.right - xsrc.left) + || (clip_vert && xdst.bottom - xdst.top != xsrc.bottom - xsrc.top)) { - xsrc.right -= (DestRect->right - (int) This->currentDesc.Width); - xdst.right = (int) This->currentDesc.Width; + WARN("Out of screen rectangle in special case. Not handled right now.\n"); + return WINED3D_OK; } - } - if (clip_vert) - { - if (DestRect->top < 0) + + if (clip_horiz) + { + if (xdst.left < 0) + { + xsrc.left -= xdst.left; + xdst.left = 0; + } + if (xdst.right > This->currentDesc.Width) + { + xsrc.right -= (xdst.right - (int)This->currentDesc.Width); + xdst.right = (int)This->currentDesc.Width; + } + } + + if (clip_vert) { - xsrc.top -= DestRect->top; - xdst.top = 0; + if (xdst.top < 0) + { + xsrc.top -= xdst.top; + xdst.top = 0; + } + if (xdst.bottom > This->currentDesc.Height) + { + xsrc.bottom -= (xdst.bottom - (int)This->currentDesc.Height); + xdst.bottom = (int)This->currentDesc.Height; + } } - if (DestRect->bottom > This->currentDesc.Height) + + /* And check if after clipping something is still to be done... */ + if ((xdst.right <= 0) || (xdst.bottom <= 0) + || (xdst.left >= (int)This->currentDesc.Width) + || (xdst.top >= (int)This->currentDesc.Height) + || (xsrc.right <= 0) || (xsrc.bottom <= 0) + || (xsrc.left >= (int) Src->currentDesc.Width) + || (xsrc.top >= (int)Src->currentDesc.Height)) { - xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height); - xdst.bottom = (int) This->currentDesc.Height; + TRACE("Nothing to be done after clipping.\n"); + return WINED3D_OK; } } - /* And check if after clipping something is still to be done... */ - if ((xdst.bottom <= 0) || (xdst.right <= 0) || - (xdst.top >= (int) This->currentDesc.Height) || - (xdst.left >= (int) This->currentDesc.Width) || - (xsrc.bottom <= 0) || (xsrc.right <= 0) || - (xsrc.top >= (int) Src->currentDesc.Height) || - (xsrc.left >= (int) Src->currentDesc.Width)) - { - TRACE("Nothing to be done after clipping !\n"); - return WINED3D_OK; - } } } + else + { + xdst.left = 0; + xdst.top = 0; + xdst.right = This->currentDesc.Width; + xdst.bottom = This->currentDesc.Height; + } if (Src == This) { @@ -1552,7 +1600,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dst RECT lock_src, lock_dst, lock_union; const BYTE *sbuf; BYTE *dbuf; - const struct GlPixelFormatDesc *sEntry, *dEntry; + const struct wined3d_format_desc *sEntry, *dEntry; if (TRACE_ON(d3d_surface)) { @@ -1833,7 +1881,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DL } else { - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; + const struct wined3d_format_desc *format_desc = This->resource.format_desc; TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); diff --git a/reactos/dll/directx/wine/wined3d/surface_gdi.c b/reactos/dll/directx/wine/wined3d/surface_gdi.c index 3f09dc3c130..580c88a9080 100644 --- a/reactos/dll/directx/wine/wined3d/surface_gdi.c +++ b/reactos/dll/directx/wine/wined3d/surface_gdi.c @@ -200,7 +200,7 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface) /* Tell the swapchain to update the screen */ if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { - if(iface == swapchain->frontBuffer) + if (This == swapchain->front_buffer) { x11_copy_to_screen(swapchain, &This->lockedRect); } @@ -240,7 +240,8 @@ IWineGDISurfaceImpl_Flip(IWineD3DSurface *iface, return WINEDDERR_NOTFLIPPABLE; } - hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0); + hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *)swapchain, + NULL, NULL, swapchain->win_handle, NULL, 0); IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return hr; } @@ -296,9 +297,9 @@ const char* filename) FILE* f = NULL; UINT y = 0, x = 0; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + const struct wined3d_format_desc *format_desc = This->resource.format_desc; static char *output = NULL; static UINT size = 0; - const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; if (This->pow2Width > size) { output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pow2Width * 3); @@ -340,14 +341,13 @@ const char* filename) fwrite(output, 3 * This->pow2Width, 1, f); } } else { - int red_shift, green_shift, blue_shift, pix_width, alpha_shift; + int red_shift, green_shift, blue_shift, pix_width; pix_width = format_desc->byte_count; red_shift = get_shift(format_desc->red_mask); green_shift = get_shift(format_desc->green_mask); blue_shift = get_shift(format_desc->blue_mask); - alpha_shift = get_shift(format_desc->alpha_mask); for (y = 0; y < This->pow2Height; y++) { const unsigned char *src = This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface)); @@ -366,8 +366,8 @@ const char* filename) output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift; comp = color & format_desc->green_mask; output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift; - comp = color & format_desc->alpha_mask; - output[3 * x + 2] = alpha_shift > 0 ? comp >> alpha_shift : comp << -alpha_shift; + comp = color & format_desc->blue_mask; + output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift; } fwrite(output, 3 * This->pow2Width, 1, f); } @@ -430,7 +430,7 @@ static HRESULT WINAPI IWineGDISurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHD IWineD3DSurfaceImpl *dds_primary; IWineD3DSwapChainImpl *swapchain; swapchain = (IWineD3DSwapChainImpl *)This->resource.device->swapchains[0]; - dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer; + dds_primary = swapchain->front_buffer; if (dds_primary && dds_primary->palette) pal = dds_primary->palette->palents; } @@ -500,7 +500,7 @@ static HRESULT WINAPI IWineGDISurfaceImpl_RealizePalette(IWineD3DSurface *iface) /* Tell the swapchain to update the screen */ if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { - if(iface == swapchain->frontBuffer) + if (This == swapchain->front_buffer) { x11_copy_to_screen(swapchain, NULL); } diff --git a/reactos/dll/directx/wine/wined3d/swapchain.c b/reactos/dll/directx/wine/wined3d/swapchain.c index cbdb961f705..b0d591a7587 100644 --- a/reactos/dll/directx/wine/wined3d/swapchain.c +++ b/reactos/dll/directx/wine/wined3d/swapchain.c @@ -33,8 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(fps); -#define GLINFO_LOCATION This->device->adapter->gl_info - /*IWineD3DSwapChain parts follow: */ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface) { @@ -46,32 +44,32 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface) IWineD3DSwapChain_SetGammaRamp(iface, 0, &This->orig_gamma); - /* Release the swapchain's draw buffers. Make sure This->backBuffer[0] is + /* Release the swapchain's draw buffers. Make sure This->back_buffers[0] is * the last buffer to be destroyed, FindContext() depends on that. */ - if (This->frontBuffer) + if (This->front_buffer) { - IWineD3DSurface_SetContainer(This->frontBuffer, 0); - if (IWineD3DSurface_Release(This->frontBuffer)) + IWineD3DSurface_SetContainer((IWineD3DSurface *)This->front_buffer, NULL); + if (IWineD3DSurface_Release((IWineD3DSurface *)This->front_buffer)) { WARN("(%p) Something's still holding the front buffer (%p).\n", - This, This->frontBuffer); + This, This->front_buffer); } - This->frontBuffer = NULL; + This->front_buffer = NULL; } - if (This->backBuffer) + if (This->back_buffers) { UINT i = This->presentParms.BackBufferCount; while (i--) { - IWineD3DSurface_SetContainer(This->backBuffer[i], 0); - if (IWineD3DSurface_Release(This->backBuffer[i])) + IWineD3DSurface_SetContainer((IWineD3DSurface *)This->back_buffers[i], NULL); + if (IWineD3DSurface_Release((IWineD3DSurface *)This->back_buffers[i])) WARN("(%p) Something's still holding back buffer %u (%p).\n", - This, i, This->backBuffer[i]); + This, i, This->back_buffers[i]); } - HeapFree(GetProcessHeap(), 0, This->backBuffer); - This->backBuffer = NULL; + HeapFree(GetProcessHeap(), 0, This->back_buffers); + This->back_buffers = NULL; } for (i = 0; i < This->num_contexts; ++i) @@ -100,11 +98,13 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * const RECT *src_rect, const RECT *dst_rect) { IWineD3DDeviceImpl *device = This->device; - IWineD3DSurfaceImpl *backbuffer = ((IWineD3DSurfaceImpl *) This->backBuffer[0]); + IWineD3DSurfaceImpl *backbuffer = This->back_buffers[0]; UINT src_w = src_rect->right - src_rect->left; UINT src_h = src_rect->bottom - src_rect->top; GLenum gl_filter; const struct wined3d_gl_info *gl_info = context->gl_info; + RECT win_rect; + UINT win_h; TRACE("swapchain %p, context %p, src_rect %s, dst_rect %s.\n", This, context, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect)); @@ -114,12 +114,14 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * else gl_filter = GL_LINEAR; - if (gl_info->fbo_ops.glBlitFramebuffer) + GetClientRect(This->win_handle, &win_rect); + win_h = win_rect.bottom - win_rect.top; + + if (gl_info->fbo_ops.glBlitFramebuffer && is_identity_fixup(backbuffer->resource.format_desc->color_fixup)) { ENTER_GL(); - context_bind_fbo(context, GL_READ_FRAMEBUFFER, &context->src_fbo); - context_attach_surface_fbo(context, GL_READ_FRAMEBUFFER, 0, This->backBuffer[0]); - context_attach_depth_stencil_fbo(context, GL_READ_FRAMEBUFFER, NULL, FALSE); + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL); + glReadBuffer(GL_COLOR_ATTACHMENT0); context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL); context_set_draw_buffer(context, GL_BACK); @@ -129,8 +131,8 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * /* Note that the texture is upside down */ gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, - dst_rect->left, dst_rect->bottom, dst_rect->right, dst_rect->top, - GL_COLOR_BUFFER_BIT, gl_filter); + dst_rect->left, win_h - dst_rect->top, dst_rect->right, win_h - dst_rect->bottom, + GL_COLOR_BUFFER_BIT, gl_filter); checkGLcall("Swapchain present blit(EXT_framebuffer_blit)\n"); LEAVE_GL(); } @@ -142,7 +144,8 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * float tex_right = src_rect->right; float tex_bottom = src_rect->bottom; - context2 = context_acquire(This->device, This->backBuffer[0], CTXUSAGE_BLIT); + context2 = context_acquire(This->device, This->back_buffers[0]); + context_apply_blit_state(context2, device); if(backbuffer->Flags & SFLAG_NORMCOORD) { @@ -152,30 +155,31 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * tex_bottom /= src_h; } + if (is_complex_fixup(backbuffer->resource.format_desc->color_fixup)) + gl_filter = GL_NEAREST; + ENTER_GL(); context_bind_fbo(context2, GL_DRAW_FRAMEBUFFER, NULL); /* Set up the texture. The surface is not in a IWineD3D*Texture container, * so there are no d3d texture settings to dirtify */ - device->blitter->set_shader((IWineD3DDevice *) device, backbuffer->resource.format_desc, - backbuffer->texture_target, backbuffer->pow2Width, - backbuffer->pow2Height); - glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + device->blitter->set_shader((IWineD3DDevice *) device, backbuffer); + glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter); + glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, gl_filter); context_set_draw_buffer(context, GL_BACK); /* Set the viewport to the destination rectandle, disable any projection - * transformation set up by CTXUSAGE_BLIT, and draw a (-1,-1)-(1,1) quad. + * transformation set up by context_apply_blit_state(), and draw a + * (-1,-1)-(1,1) quad. * * Back up viewport and matrix to avoid breaking last_was_blit * - * Note that CTXUSAGE_BLIT set up viewport and ortho to match the surface - * size - we want the GL drawable(=window) size. - */ + * Note that context_apply_blit_state() set up viewport and ortho to + * match the surface size - we want the GL drawable(=window) size. */ glPushAttrib(GL_VIEWPORT_BIT); - glViewport(dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom); + glViewport(dst_rect->left, win_h - dst_rect->bottom, dst_rect->right, win_h - dst_rect->top); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); @@ -211,6 +215,7 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context * static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + const struct wined3d_gl_info *gl_info; struct wined3d_context *context; RECT src_rect, dst_rect; BOOL render_to_fbo; @@ -219,7 +224,15 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO IWineD3DSwapChain_SetDestWindowOverride(iface, hDestWindowOverride); - context = context_acquire(This->device, This->backBuffer[0], CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->device, This->back_buffers[0]); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping present.\n"); + return WINED3D_OK; + } + + gl_info = context->gl_info; /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ if (This->device->bCursorVisible && This->device->cursorTexture) @@ -242,17 +255,13 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO cursor.resource.ref = 1; cursor.resource.device = This->device; cursor.resource.pool = WINED3DPOOL_SCRATCH; - cursor.resource.format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, context->gl_info); + cursor.resource.format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info); cursor.resource.resourceType = WINED3DRTYPE_SURFACE; cursor.texture_name = This->device->cursorTexture; cursor.texture_target = GL_TEXTURE_2D; cursor.texture_level = 0; cursor.currentDesc.Width = This->device->cursorWidth; cursor.currentDesc.Height = This->device->cursorHeight; - cursor.glRect.left = 0; - cursor.glRect.top = 0; - cursor.glRect.right = cursor.currentDesc.Width; - cursor.glRect.bottom = cursor.currentDesc.Height; /* The cursor must have pow2 sizes */ cursor.pow2Width = cursor.currentDesc.Width; cursor.pow2Height = cursor.currentDesc.Height; @@ -264,14 +273,15 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO if (This->presentParms.Windowed) { MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2); } - IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *)&cursor, + IWineD3DSurface_Blt((IWineD3DSurface *)This->back_buffers[0], &destRect, (IWineD3DSurface *)&cursor, NULL, WINEDDBLT_KEYSRC, NULL, WINED3DTEXF_POINT); } if (This->device->logo_surface) { /* Blit the logo into the upper left corner of the drawable. */ - IWineD3DSurface_BltFast(This->backBuffer[0], 0, 0, This->device->logo_surface, NULL, WINEDDBLTFAST_SRCCOLORKEY); + IWineD3DSurface_BltFast((IWineD3DSurface *)This->back_buffers[0], 0, 0, + This->device->logo_surface, NULL, WINEDDBLTFAST_SRCCOLORKEY); } TRACE("Presenting HDC %p.\n", context->hdc); @@ -315,8 +325,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO */ if (!This->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - IWineD3DSurface_LoadLocation(This->backBuffer[0], SFLAG_INTEXTURE, NULL); - IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, FALSE); + IWineD3DSurface_LoadLocation((IWineD3DSurface *)This->back_buffers[0], SFLAG_INTEXTURE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)This->back_buffers[0], SFLAG_INDRAWABLE, FALSE); This->render_to_fbo = TRUE; /* Force the context manager to update the render target configuration next draw. */ @@ -420,14 +430,14 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO WINED3DCLEAR_TARGET, 0xff00ffff, 1.0f, 0); } - if(!This->render_to_fbo && - ( ((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_INSYSMEM || - ((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_INSYSMEM ) ) { + if (!This->render_to_fbo && ((This->front_buffer->Flags & SFLAG_INSYSMEM) + || (This->back_buffers[0]->Flags & SFLAG_INSYSMEM))) + { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ - IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; - IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; + IWineD3DSurfaceImpl *front = This->front_buffer; + IWineD3DSurfaceImpl *back = This->back_buffers[0]; if(front->resource.size == back->resource.size) { DWORD fbflags; @@ -438,35 +448,45 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO * This serves to update the emulated overlay, if any */ fbflags = front->Flags; - IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)front, SFLAG_INDRAWABLE, TRUE); front->Flags = fbflags; } else { IWineD3DSurface_ModifyLocation((IWineD3DSurface *) front, SFLAG_INDRAWABLE, TRUE); IWineD3DSurface_ModifyLocation((IWineD3DSurface *) back, SFLAG_INDRAWABLE, TRUE); } - } else { - IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); + } + else + { + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)This->front_buffer, SFLAG_INDRAWABLE, TRUE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, * the texture / sysmem copy needs to be reloaded from the drawable */ - if(This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP) { - IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, TRUE); + if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP) + { + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)This->back_buffers[0], SFLAG_INDRAWABLE, TRUE); } } - if (This->device->stencilBufferTarget) + if (This->device->depth_stencil) { if (This->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL - || ((IWineD3DSurfaceImpl *)This->device->stencilBufferTarget)->Flags & SFLAG_DISCARD) + || This->device->depth_stencil->Flags & SFLAG_DISCARD) { - surface_modify_ds_location(This->device->stencilBufferTarget, SFLAG_DS_DISCARDED); + surface_modify_ds_location(This->device->depth_stencil, SFLAG_DS_DISCARDED, + This->device->depth_stencil->currentDesc.Width, + This->device->depth_stencil->currentDesc.Height); + if (This->device->depth_stencil == This->device->onscreen_depth_stencil) + { + IWineD3DSurface_Release((IWineD3DSurface *)This->device->onscreen_depth_stencil); + This->device->onscreen_depth_stencil = NULL; + } } } if (This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE - && context->gl_info->supported[SGI_VIDEO_SYNC]) + && gl_info->supported[SGI_VIDEO_SYNC]) { retval = GL_EXTCALL(glXGetVideoSyncSGI(&sync)); if(retval != 0) { @@ -514,47 +534,16 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO return WINED3D_OK; } -static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - WINED3DLOCKED_RECT r; - BYTE *mem; - - if (!window || window == This->win_handle) return WINED3D_OK; - - TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, window); - if (This->context[0] == This->device->contexts[0]) - { - /* The primary context 'owns' all the opengl resources. Destroying and recreating that context requires downloading - * all opengl resources, deleting the gl resources, destroying all other contexts, then recreating all other contexts - * and reload the resources - */ - delete_opengl_contexts((IWineD3DDevice *)This->device, iface); - This->win_handle = window; - create_primary_opengl_context((IWineD3DDevice *)This->device, iface); - } - else - { - This->win_handle = window; +static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) +{ + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)iface; - /* The old back buffer has to be copied over to the new back buffer. A lockrect - switchcontext - unlockrect - * would suffice in theory, but it is rather nasty and may cause troubles with future changes of the locking code - * So lock read only, copy the surface out, then lock with the discard flag and write back - */ - IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_READONLY); - mem = HeapAlloc(GetProcessHeap(), 0, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - memcpy(mem, r.pBits, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - IWineD3DSurface_UnlockRect(This->backBuffer[0]); + if (!window) window = swapchain->device_window; + if (window == swapchain->win_handle) return WINED3D_OK; - context_destroy(This->device, This->context[0]); - This->context[0] = context_create(This->device, (IWineD3DSurfaceImpl *)This->frontBuffer, - This->win_handle, FALSE /* pbuffer */, &This->presentParms); - context_release(This->context[0]); + TRACE("Setting swapchain %p window from %p to %p\n", swapchain, swapchain->win_handle, window); + swapchain->win_handle = window; - IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_DISCARD); - memcpy(r.pBits, mem, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - HeapFree(GetProcessHeap(), 0, mem); - IWineD3DSurface_UnlockRect(This->backBuffer[0]); - } return WINED3D_OK; } @@ -599,7 +588,7 @@ static LONG fullscreen_exstyle(LONG exstyle) void swapchain_setup_fullscreen_window(IWineD3DSwapChainImpl *swapchain, UINT w, UINT h) { IWineD3DDeviceImpl *device = swapchain->device; - HWND window = swapchain->win_handle; + HWND window = swapchain->device_window; BOOL filter_messages; LONG style, exstyle; @@ -633,7 +622,7 @@ void swapchain_setup_fullscreen_window(IWineD3DSwapChainImpl *swapchain, UINT w, void swapchain_restore_fullscreen_window(IWineD3DSwapChainImpl *swapchain) { IWineD3DDeviceImpl *device = swapchain->device; - HWND window = swapchain->win_handle; + HWND window = swapchain->device_window; BOOL filter_messages; LONG style, exstyle; @@ -671,7 +660,7 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, IUnknown *parent) { const struct wined3d_adapter *adapter = device->adapter; - const struct GlPixelFormatDesc *format_desc; + const struct wined3d_format_desc *format_desc; BOOL displaymode_set = FALSE; WINED3DDISPLAYMODE mode; RECT client_rect; @@ -713,6 +702,7 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface swapchain->parent = parent; swapchain->ref = 1; swapchain->win_handle = window; + swapchain->device_window = window; if (!present_parameters->Windowed && window) { @@ -768,18 +758,19 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface hr = IWineD3DDeviceParent_CreateRenderTarget(device->device_parent, parent, swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight, swapchain->presentParms.BackBufferFormat, swapchain->presentParms.MultiSampleType, - swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, &swapchain->frontBuffer); + swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, + (IWineD3DSurface **)&swapchain->front_buffer); if (FAILED(hr)) { WARN("Failed to create front buffer, hr %#x.\n", hr); goto err; } - IWineD3DSurface_SetContainer(swapchain->frontBuffer, (IWineD3DBase *)swapchain); - ((IWineD3DSurfaceImpl *)swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN; + IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->front_buffer, (IWineD3DBase *)swapchain); + swapchain->front_buffer->Flags |= SFLAG_SWAPCHAIN; if (surface_type == SURFACE_OPENGL) { - IWineD3DSurface_ModifyLocation(swapchain->frontBuffer, SFLAG_INDRAWABLE, TRUE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE); } /* MSDN says we're only allowed a single fullscreen swapchain per device, @@ -816,14 +807,49 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface if (surface_type == SURFACE_OPENGL) { - swapchain->context[0] = context_create(device, (IWineD3DSurfaceImpl *)swapchain->frontBuffer, - window, FALSE /* pbuffer */, present_parameters); + WINED3DFORMAT formats[] = + { + WINED3DFMT_D24_UNORM_S8_UINT, + WINED3DFMT_D32_UNORM, + WINED3DFMT_R24_UNORM_X8_TYPELESS, + WINED3DFMT_D16_UNORM, + WINED3DFMT_S1_UINT_D15_UNORM + }; + + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + + /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate. + * You are able to add a depth + stencil surface at a later stage when you need it. + * In order to support this properly in WineD3D we need the ability to recreate the opengl context and + * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new + * context, need torecreate shaders, textures and other resources. + * + * The context manager already takes care of the state problem and for the other tasks code from Reset + * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now. + * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the + * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this + * issue needs to be fixed. */ + for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++) + { + swapchain->ds_format = getFormatDescEntry(formats[i], gl_info); + swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format); + if (swapchain->context[0]) break; + TRACE("Depth stencil format %s is not supported, trying next format\n", + debug_d3dformat(formats[i])); + } + if (!swapchain->context[0]) { WARN("Failed to create context.\n"); hr = WINED3DERR_NOTAVAILABLE; goto err; } + + if (!present_parameters->EnableAutoDepthStencil + || swapchain->presentParms.AutoDepthStencilFormat != swapchain->ds_format->format) + { + FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n"); + } context_release(swapchain->context[0]); } else @@ -833,9 +859,9 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface if (swapchain->presentParms.BackBufferCount > 0) { - swapchain->backBuffer = HeapAlloc(GetProcessHeap(), 0, - sizeof(*swapchain->backBuffer) * swapchain->presentParms.BackBufferCount); - if (!swapchain->backBuffer) + swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0, + sizeof(*swapchain->back_buffers) * swapchain->presentParms.BackBufferCount); + if (!swapchain->back_buffers) { ERR("Failed to allocate backbuffer array memory.\n"); hr = E_OUTOFMEMORY; @@ -848,15 +874,16 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface hr = IWineD3DDeviceParent_CreateRenderTarget(device->device_parent, parent, swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight, swapchain->presentParms.BackBufferFormat, swapchain->presentParms.MultiSampleType, - swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, &swapchain->backBuffer[i]); + swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, + (IWineD3DSurface **)&swapchain->back_buffers[i]); if (FAILED(hr)) { WARN("Failed to create back buffer %u, hr %#x.\n", i, hr); goto err; } - IWineD3DSurface_SetContainer(swapchain->backBuffer[i], (IWineD3DBase *)swapchain); - ((IWineD3DSurfaceImpl *)swapchain->backBuffer[i])->Flags |= SFLAG_SWAPCHAIN; + IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->back_buffers[i], (IWineD3DBase *)swapchain); + swapchain->back_buffers[i]->Flags |= SFLAG_SWAPCHAIN; } } @@ -864,20 +891,20 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface if (present_parameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL) { TRACE("Creating depth/stencil buffer.\n"); - if (!device->auto_depth_stencil_buffer) + if (!device->auto_depth_stencil) { hr = IWineD3DDeviceParent_CreateDepthStencilSurface(device->device_parent, parent, swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight, swapchain->presentParms.AutoDepthStencilFormat, swapchain->presentParms.MultiSampleType, swapchain->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */, - &device->auto_depth_stencil_buffer); + (IWineD3DSurface **)&device->auto_depth_stencil); if (FAILED(hr)) { WARN("Failed to create the auto depth stencil, hr %#x.\n", hr); goto err; } - IWineD3DSurface_SetContainer(device->auto_depth_stencil_buffer, NULL); + IWineD3DSurface_SetContainer((IWineD3DSurface *)device->auto_depth_stencil, NULL); } } @@ -902,13 +929,13 @@ err: ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL); } - if (swapchain->backBuffer) + if (swapchain->back_buffers) { for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i) { - if (swapchain->backBuffer[i]) IWineD3DSurface_Release(swapchain->backBuffer[i]); + if (swapchain->back_buffers[i]) IWineD3DSurface_Release((IWineD3DSurface *)swapchain->back_buffers[i]); } - HeapFree(GetProcessHeap(), 0, swapchain->backBuffer); + HeapFree(GetProcessHeap(), 0, swapchain->back_buffers); } if (swapchain->context) @@ -922,7 +949,7 @@ err: HeapFree(GetProcessHeap(), 0, swapchain->context); } - if (swapchain->frontBuffer) IWineD3DSurface_Release(swapchain->frontBuffer); + if (swapchain->front_buffer) IWineD3DSurface_Release((IWineD3DSurface *)swapchain->front_buffer); return hr; } @@ -935,9 +962,7 @@ struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *i TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId()); - ctx = context_create(This->device, (IWineD3DSurfaceImpl *)This->frontBuffer, - This->context[0]->win_handle, FALSE /* pbuffer */, &This->presentParms); - if (!ctx) + if (!(ctx = context_create(This, This->front_buffer, This->ds_format))) { ERR("Failed to create a new context for the swapchain\n"); return NULL; @@ -962,9 +987,8 @@ struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *i void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) { - IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->current_rt; /* The drawable size of an onscreen drawable is the surface size. * (Actually: The window size, but the surface is created in window size) */ - *width = surface->currentDesc.Width; - *height = surface->currentDesc.Height; + *width = context->current_rt->currentDesc.Width; + *height = context->current_rt->currentDesc.Height; } diff --git a/reactos/dll/directx/wine/wined3d/swapchain_base.c b/reactos/dll/directx/wine/wined3d/swapchain_base.c index 4c0590e4691..1817de2079a 100644 --- a/reactos/dll/directx/wine/wined3d/swapchain_base.c +++ b/reactos/dll/directx/wine/wined3d/swapchain_base.c @@ -85,7 +85,7 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *i MapWindowPoints(This->win_handle, NULL, &start, 1); } - IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0); + IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, (IWineD3DSurface *)This->front_buffer, NULL, 0); return WINED3D_OK; } @@ -106,12 +106,13 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, * used (there This->backBuffer is always NULL). We need this because this function has * to be called from IWineD3DStateBlockImpl_InitStartupStateBlock to get the default * scissorrect dimensions. */ - if( !This->backBuffer ) { + if (!This->back_buffers) + { *ppBackBuffer = NULL; return WINED3DERR_INVALIDCALL; } - *ppBackBuffer = This->backBuffer[iBackBuffer]; + *ppBackBuffer = (IWineD3DSurface *)This->back_buffers[iBackBuffer]; TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer); /* Note inc ref on returned surface */ @@ -145,15 +146,14 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface return hr; } -HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) { +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice **device) +{ IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - *ppDevice = (IWineD3DDevice *)This->device; + *device = (IWineD3DDevice *)This->device; + IWineD3DDevice_AddRef(*device); - /* Note Calling this method will increase the internal reference count - on the IDirect3DDevice9 interface. */ - IWineD3DDevice_AddRef(*ppDevice); - TRACE("(%p) : returning %p\n", This, *ppDevice); + TRACE("(%p) : returning %p\n", This, *device); return WINED3D_OK; } @@ -171,9 +171,9 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; HDC hDC; TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags); - hDC = GetDC(This->win_handle); + hDC = GetDC(This->device_window); SetDeviceGammaRamp(hDC, (LPVOID)pRamp); - ReleaseDC(This->win_handle, hDC); + ReleaseDC(This->device_window, hDC); return WINED3D_OK; } @@ -183,9 +183,9 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; HDC hDC; TRACE("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); + hDC = GetDC(This->device_window); GetDeviceGammaRamp(hDC, pRamp); - ReleaseDC(This->win_handle, hDC); + ReleaseDC(This->device_window, hDC); return WINED3D_OK; } diff --git a/reactos/dll/directx/wine/wined3d/swapchain_gdi.c b/reactos/dll/directx/wine/wined3d/swapchain_gdi.c index c437b419f8e..b80352c1dce 100644 --- a/reactos/dll/directx/wine/wined3d/swapchain_gdi.c +++ b/reactos/dll/directx/wine/wined3d/swapchain_gdi.c @@ -37,24 +37,27 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface) IWineD3DSwapChain_SetGammaRamp(iface, 0, &This->orig_gamma); /* release the ref to the front and back buffer parents */ - if(This->frontBuffer) { - IWineD3DSurface_SetContainer(This->frontBuffer, 0); - if (IWineD3DSurface_Release(This->frontBuffer) > 0) + if (This->front_buffer) + { + IWineD3DSurface_SetContainer((IWineD3DSurface *)This->front_buffer, NULL); + if (IWineD3DSurface_Release((IWineD3DSurface *)This->front_buffer) > 0) { WARN("(%p) Something's still holding the front buffer\n",This); } } - if(This->backBuffer) { + if (This->back_buffers) + { UINT i; - for(i = 0; i < This->presentParms.BackBufferCount; i++) { - IWineD3DSurface_SetContainer(This->backBuffer[i], 0); - if (IWineD3DSurface_Release(This->backBuffer[i]) > 0) + for (i = 0; i < This->presentParms.BackBufferCount; ++i) + { + IWineD3DSurface_SetContainer((IWineD3DSurface *)This->back_buffers[i], NULL); + if (IWineD3DSurface_Release((IWineD3DSurface *)This->back_buffers[i])) { WARN("(%p) Something's still holding the back buffer\n",This); } } - HeapFree(GetProcessHeap(), 0, This->backBuffer); + HeapFree(GetProcessHeap(), 0, This->back_buffers); } /* Restore the screen resolution if we rendered in fullscreen @@ -86,7 +89,7 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface) *****************************************************************************/ void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) { - IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; + IWineD3DSurfaceImpl *front = This->front_buffer; if(front->resource.usage & WINED3DUSAGE_RENDERTARGET) { POINT offset = {0,0}; @@ -172,12 +175,13 @@ static HRESULT WINAPI IWineGDISwapChainImpl_Present(IWineD3DSwapChain *iface, CO IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface; IWineD3DSurfaceImpl *front, *back; - if(!This->backBuffer) { + if (!This->back_buffers) + { WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n"); return WINED3DERR_INVALIDCALL; } - front = (IWineD3DSurfaceImpl *) This->frontBuffer; - back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; + front = This->front_buffer; + back = This->back_buffers[0]; /* Flip the DC */ { @@ -226,7 +230,7 @@ static HRESULT WINAPI IWineGDISwapChainImpl_Present(IWineD3DSwapChain *iface, CO /* FPS support */ if (TRACE_ON(fps)) { - static long prev_time, frames; + static LONG prev_time, frames; DWORD time = GetTickCount(); frames++; diff --git a/reactos/dll/directx/wine/wined3d/texture.c b/reactos/dll/directx/wine/wined3d/texture.c index 1e272144a8a..98e7909370e 100644 --- a/reactos/dll/directx/wine/wined3d/texture.c +++ b/reactos/dll/directx/wine/wined3d/texture.c @@ -63,21 +63,22 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG { /* context_acquire() sets isInDraw to TRUE when loading a pbuffer into a texture, * thus no danger of recursive calls. */ - context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL); } if (This->resource.format_desc->format == WINED3DFMT_P8_UINT || This->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - if (palette9_changed((IWineD3DSurfaceImpl *)This->surfaces[i])) + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + if (palette9_changed(surface)) { TRACE("Reloading surface because the d3d8/9 palette was changed.\n"); /* TODO: This is not necessarily needed with hw palettized texture support. */ - IWineD3DSurface_LoadLocation(This->surfaces[i], SFLAG_INSYSMEM, NULL); + IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INSYSMEM, NULL); /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */ - IWineD3DSurface_ModifyLocation(This->surfaces[i], SFLAG_INTEXTURE, FALSE); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INTEXTURE, FALSE); } } } @@ -86,9 +87,9 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG * since the last load then reload the surfaces. */ if (*dirty) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); + IWineD3DSurface_LoadTexture((IWineD3DSurface *)This->baseTexture.sub_resources[i], srgb_mode); } } else @@ -108,17 +109,18 @@ static void texture_cleanup(IWineD3DTextureImpl *This) TRACE("(%p) : Cleaning up\n", This); - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - if (This->surfaces[i]) + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + if (surface) { /* Clean out the texture name we gave to the surface so that the * surface doesn't try and release it */ - surface_set_texture_name(This->surfaces[i], 0, TRUE); - surface_set_texture_name(This->surfaces[i], 0, FALSE); - surface_set_texture_target(This->surfaces[i], 0); - IWineD3DSurface_SetContainer(This->surfaces[i], 0); - IWineD3DSurface_Release(This->surfaces[i]); + surface_set_texture_name(surface, 0, TRUE); + surface_set_texture_name(surface, 0, FALSE); + surface_set_texture_target(surface, 0); + IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL); + IWineD3DSurface_Release((IWineD3DSurface *)surface); } } @@ -204,10 +206,12 @@ static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) { * surface before, this one will be a NOP and vice versa. Unloading an unloaded * surface is fine */ - for (i = 0; i < This->baseTexture.levels; i++) { - IWineD3DSurface_UnLoad(This->surfaces[i]); - surface_set_texture_name(This->surfaces[i], 0, FALSE); /* Delete rgb name */ - surface_set_texture_name(This->surfaces[i], 0, TRUE); /* delete srgb name */ + for (i = 0; i < This->baseTexture.level_count; ++i) + { + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + IWineD3DSurface_UnLoad((IWineD3DSurface *)surface); + surface_set_texture_name(surface, 0, FALSE); /* Delete rgb name */ + surface_set_texture_name(surface, 0, TRUE); /* delete srgb name */ } basetexture_unload((IWineD3DBaseTexture *)iface); @@ -276,14 +280,20 @@ static HRESULT WINAPI IWineD3DTextureImpl_BindTexture(IWineD3DTexture *iface, BO gl_tex = &This->baseTexture.texture_rgb; } - for (i = 0; i < This->baseTexture.levels; ++i) { - surface_set_texture_name(This->surfaces[i], gl_tex->name, This->baseTexture.is_srgb); + for (i = 0; i < This->baseTexture.level_count; ++i) + { + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)This->baseTexture.sub_resources[i]; + surface_set_texture_name(surface, gl_tex->name, This->baseTexture.is_srgb); } - /* Conditinal non power of two textures use a different clamping default. If we're using the GL_WINE_normalized_texrect - * partial driver emulation, we're dealing with a GL_TEXTURE_2D texture which has the address mode set to repeat - something - * that prevents us from hitting the accelerated codepath. Thus manually set the GL state. The same applies to filtering. - * Even if the texture has only one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW fallback on macos. - */ + + /* Conditinal non power of two textures use a different clamping + * default. If we're using the GL_WINE_normalized_texrect partial + * driver emulation, we're dealing with a GL_TEXTURE_2D texture which + * has the address mode set to repeat - something that prevents us + * from hitting the accelerated codepath. Thus manually set the GL + * state. The same applies to filtering. Even if the texture has only + * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW + * fallback on macos. */ if(IWineD3DBaseTexture_IsCondNP2(iface)) { ENTER_GL(); glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -323,72 +333,94 @@ static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) { /* ******************************************* IWineD3DTexture IWineD3DTexture parts follow ******************************************* */ -static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; +static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, UINT level, WINED3DSURFACE_DESC *desc) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); - if (Level < This->baseTexture.levels) { - TRACE("(%p) Level (%d)\n", This, Level); - return IWineD3DSurface_GetDesc(This->surfaces[Level], pDesc); + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - return WINED3DERR_INVALIDCALL; + + return IWineD3DSurface_GetDesc(surface, desc); } -static HRESULT WINAPI IWineD3DTextureImpl_GetSurfaceLevel(IWineD3DTexture *iface, UINT Level, IWineD3DSurface** ppSurfaceLevel) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - HRESULT hr = WINED3DERR_INVALIDCALL; +static HRESULT WINAPI IWineD3DTextureImpl_GetSurfaceLevel(IWineD3DTexture *iface, + UINT level, IWineD3DSurface **surface) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *s; - if (Level < This->baseTexture.levels) { - *ppSurfaceLevel = This->surfaces[Level]; - IWineD3DSurface_AddRef(This->surfaces[Level]); - hr = WINED3D_OK; - TRACE("(%p) : returning %p for level %d\n", This, *ppSurfaceLevel, Level); - } - if (WINED3D_OK != hr) { - WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - *ppSurfaceLevel = NULL; /* Just to be on the safe side.. */ + TRACE("iface %p, level %u, surface %p.\n", iface, level, surface); + + if (!(s = (IWineD3DSurface *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + IWineD3DSurface_AddRef(s); + *surface = s; + + TRACE("Returning surface %p.\n", *surface); + + return WINED3D_OK; } -static HRESULT WINAPI IWineD3DTextureImpl_LockRect(IWineD3DTexture *iface, UINT Level, WINED3DLOCKED_RECT *pLockedRect, - CONST RECT *pRect, DWORD Flags) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - HRESULT hr = WINED3DERR_INVALIDCALL; +static HRESULT WINAPI IWineD3DTextureImpl_LockRect(IWineD3DTexture *iface, + UINT level, WINED3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; - if (Level < This->baseTexture.levels) { - hr = IWineD3DSurface_LockRect(This->surfaces[Level], pLockedRect, pRect, Flags); - } - if (WINED3D_OK == hr) { - TRACE("(%p) Level (%d) success\n", This, Level); - } else { - WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); + TRACE("iface %p, level %u, locked_rect %p, rect %s, flags %#x.\n", + iface, level, locked_rect, wine_dbgstr_rect(rect), flags); + + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + return IWineD3DSurface_LockRect(surface, locked_rect, rect, flags); } -static HRESULT WINAPI IWineD3DTextureImpl_UnlockRect(IWineD3DTexture *iface, UINT Level) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - HRESULT hr = WINED3DERR_INVALIDCALL; +static HRESULT WINAPI IWineD3DTextureImpl_UnlockRect(IWineD3DTexture *iface, UINT level) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurface *surface; - if (Level < This->baseTexture.levels) { - hr = IWineD3DSurface_UnlockRect(This->surfaces[Level]); - } - if ( WINED3D_OK == hr) { - TRACE("(%p) Level (%d) success\n", This, Level); - } else { - WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); + TRACE("iface %p, level %u.\n", iface, level); + + if (!(surface = (IWineD3DSurface *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + return IWineD3DSurface_UnlockRect(surface); } -static HRESULT WINAPI IWineD3DTextureImpl_AddDirtyRect(IWineD3DTexture *iface, CONST RECT* pDirtyRect) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - This->baseTexture.texture_rgb.dirty = TRUE; - This->baseTexture.texture_srgb.dirty = TRUE; - TRACE("(%p) : dirtyfication of surface Level (0)\n", This); - surface_add_dirty_rect(This->surfaces[0], pDirtyRect); +static HRESULT WINAPI IWineD3DTextureImpl_AddDirtyRect(IWineD3DTexture *iface, const RECT *dirty_rect) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DSurfaceImpl *surface; + + TRACE("iface %p, dirty_rect %s.\n", iface, wine_dbgstr_rect(dirty_rect)); + + if (!(surface = (IWineD3DSurfaceImpl *)basetexture_get_sub_resource(texture, 0, 0))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; + } + + texture->baseTexture.texture_rgb.dirty = TRUE; + texture->baseTexture.texture_srgb.dirty = TRUE; + surface_add_dirty_rect(surface, dirty_rect); return WINED3D_OK; } @@ -434,7 +466,7 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); UINT pow2_width, pow2_height; UINT tmp_w, tmp_h; unsigned int i; @@ -497,8 +529,8 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT texture->lpVtbl = &IWineD3DTexture_Vtbl; - hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_TEXTURE, - device, 0, usage, format_desc, pool, parent, parent_ops); + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, 1, levels, + WINED3DRTYPE_TEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); @@ -565,22 +597,24 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT /* Generate all the surfaces. */ tmp_w = width; tmp_h = height; - for (i = 0; i < texture->baseTexture.levels; ++i) + for (i = 0; i < texture->baseTexture.level_count; ++i) { + IWineD3DSurface *surface; + /* Use the callback to create the texture surface. */ hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format, - usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i]); - if (FAILED(hr) || ((IWineD3DSurfaceImpl *)texture->surfaces[i])->Flags & SFLAG_OVERSIZE) + usage, pool, i, 0, &surface); + if (FAILED(hr)) { FIXME("Failed to create surface %p, hr %#x\n", texture, hr); - texture->surfaces[i] = NULL; texture_cleanup(texture); return hr; } - IWineD3DSurface_SetContainer(texture->surfaces[i], (IWineD3DBase *)texture); - TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[i]); - surface_set_texture_target(texture->surfaces[i], texture->target); + IWineD3DSurface_SetContainer(surface, (IWineD3DBase *)texture); + surface_set_texture_target((IWineD3DSurfaceImpl *)surface, texture->target); + texture->baseTexture.sub_resources[i] = (IWineD3DResourceImpl *)surface; + TRACE("Created surface level %u @ %p.\n", i, surface); /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); tmp_h = max(1, tmp_h >> 1); diff --git a/reactos/dll/directx/wine/wined3d/utils.c b/reactos/dll/directx/wine/wined3d/utils.c index 2ff16752c33..b63a5f8cee8 100644 --- a/reactos/dll/directx/wine/wined3d/utils.c +++ b/reactos/dll/directx/wine/wined3d/utils.c @@ -141,31 +141,40 @@ struct wined3d_format_base_flags static const struct wined3d_format_base_flags format_base_flags[] = { - {WINED3DFMT_UYVY, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_YUY2, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_YV12, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_DXT1, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_DXT2, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_DXT3, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_DXT4, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_DXT5, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_MULTI2_ARGB8, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_G8R8_G8B8, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_R8G8_B8G8, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_P8_UINT, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B8G8R8_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B5G5R5X1_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B5G5R5A1_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B4G4R4A4_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_B4G4R4X4_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_R8G8B8A8_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_R8G8B8X8_UNORM, WINED3DFMT_FLAG_GETDC}, - {WINED3DFMT_ATI2N, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_NVHU, WINED3DFMT_FLAG_FOURCC}, - {WINED3DFMT_NVHS, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_UYVY, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_YUY2, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_YV12, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_DXT1, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_DXT2, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_DXT3, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_DXT4, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_DXT5, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_MULTI2_ARGB8, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_G8R8_G8B8, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_R8G8_B8G8, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_P8_UINT, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B8G8R8_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B5G5R5X1_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B5G5R5A1_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B4G4R4A4_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_B4G4R4X4_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_R8G8B8A8_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_R8G8B8X8_UNORM, WINED3DFMT_FLAG_GETDC}, + {WINED3DFMT_ATI2N, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_NVHU, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_NVHS, WINED3DFMT_FLAG_FOURCC}, + {WINED3DFMT_R32_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R32G32_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R32G32B32_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R32G32B32A32_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R16_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R16G16_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_R16G16B16A16_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_D32_FLOAT, WINED3DFMT_FLAG_FLOAT}, + {WINED3DFMT_S8_UINT_D24_FLOAT, WINED3DFMT_FLAG_FLOAT}, }; struct wined3d_format_compression_info @@ -183,7 +192,7 @@ static const struct wined3d_format_compression_info format_compression_info[] = {WINED3DFMT_DXT3, 4, 4, 16}, {WINED3DFMT_DXT4, 4, 4, 16}, {WINED3DFMT_DXT5, 4, 4, 16}, - {WINED3DFMT_ATI2N, 4, 4, 16}, + {WINED3DFMT_ATI2N, 1, 1, 1}, }; struct wined3d_format_vertex_info @@ -218,20 +227,328 @@ static const struct wined3d_format_vertex_info format_vertex_info[] = {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT, 4, GL_FALSE, sizeof(GLhalfNV)} }; -typedef struct { - WINED3DFORMAT fmt; - GLint glInternal, glGammaInternal, rtInternal, glFormat, glType; - unsigned int Flags; +struct wined3d_format_texture_info +{ + WINED3DFORMAT format; + GLint gl_internal; + GLint gl_srgb_internal; + GLint gl_rt_internal; + GLint gl_format; + GLint gl_type; + unsigned int conv_byte_count; + unsigned int flags; GL_SupportedExt extension; -} GlPixelFormatDescTemplate; + void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height); +}; -/***************************************************************************** - * OpenGL format template. Contains unexciting formats which do not need - * extension checks. The order in this table is independent of the order in - * the table StaticPixelFormatDesc above. Not all formats have to be in this - * table. - */ -static const GlPixelFormatDescTemplate gl_formats_template[] = { +static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not + * format+type combination to load it. Thus convert it to A8L8, then load it + * with A4L4 internal, but A8L8 format+type + */ + unsigned int x, y; + const unsigned char *Source; + unsigned char *Dest; + UINT outpitch = pitch * 2; + + for(y = 0; y < height; y++) { + Source = src + y * pitch; + Dest = dst + y * outpitch; + for (x = 0; x < width; x++ ) { + unsigned char color = (*Source++); + /* A */ Dest[1] = (color & 0xf0) << 0; + /* L */ Dest[0] = (color & 0x0f) << 4; + Dest += 2; + } + } +} + +static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const WORD *Source; + + for(y = 0; y < height; y++) + { + unsigned short *Dest_s = (unsigned short *) (dst + y * pitch); + Source = (const WORD *)(src + y * pitch); + for (x = 0; x < width; x++ ) + { + short color = (*Source++); + unsigned char l = ((color >> 10) & 0xfc); + short v = ((color >> 5) & 0x3e); + short u = ((color ) & 0x1f); + short v_conv = v + 16; + short u_conv = u + 16; + + *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f); + Dest_s += 1; + } + } +} + +static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const WORD *Source; + unsigned char *Dest; + UINT outpitch = (pitch * 3)/2; + + /* This makes the gl surface bigger(24 bit instead of 16), but it works with + * fixed function and shaders without further conversion once the surface is + * loaded + */ + for(y = 0; y < height; y++) { + Source = (const WORD *)(src + y * pitch); + Dest = dst + y * outpitch; + for (x = 0; x < width; x++ ) { + short color = (*Source++); + unsigned char l = ((color >> 10) & 0xfc); + char v = ((color >> 5) & 0x3e); + char u = ((color ) & 0x1f); + + /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign + * and doubles the positive range. Thus shift left only once, gl does the 2nd + * shift. GL reads a signed value and converts it into an unsigned value. + */ + /* M */ Dest[2] = l << 1; + + /* Those are read as signed, but kept signed. Just left-shift 3 times to scale + * from 5 bit values to 8 bit values. + */ + /* V */ Dest[1] = v << 3; + /* U */ Dest[0] = u << 3; + Dest += 3; + } + } +} + +static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const short *Source; + unsigned char *Dest; + UINT outpitch = (pitch * 3)/2; + + for(y = 0; y < height; y++) + { + Source = (const short *)(src + y * pitch); + Dest = dst + y * outpitch; + for (x = 0; x < width; x++ ) + { + LONG color = (*Source++); + /* B */ Dest[0] = 0xff; + /* G */ Dest[1] = (color >> 8) + 128; /* V */ + /* R */ Dest[2] = (color) + 128; /* U */ + Dest += 3; + } + } +} + +static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const DWORD *Source; + unsigned char *Dest; + + /* Doesn't work correctly with the fixed function pipeline, but can work in + * shaders if the shader is adjusted. (There's no use for this format in gl's + * standard fixed function pipeline anyway). + */ + for(y = 0; y < height; y++) + { + Source = (const DWORD *)(src + y * pitch); + Dest = dst + y * pitch; + for (x = 0; x < width; x++ ) + { + LONG color = (*Source++); + /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */ + /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */ + /* R */ Dest[2] = (color & 0xff) + 128; /* U */ + Dest += 4; + } + } +} + +static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const DWORD *Source; + unsigned char *Dest; + + /* This implementation works with the fixed function pipeline and shaders + * without further modification after converting the surface. + */ + for(y = 0; y < height; y++) + { + Source = (const DWORD *)(src + y * pitch); + Dest = dst + y * pitch; + for (x = 0; x < width; x++ ) + { + LONG color = (*Source++); + /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */ + /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */ + /* U */ Dest[0] = (color & 0xff); /* U */ + /* I */ Dest[3] = 255; /* X */ + Dest += 4; + } + } +} + +static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const DWORD *Source; + unsigned char *Dest; + + for(y = 0; y < height; y++) + { + Source = (const DWORD *)(src + y * pitch); + Dest = dst + y * pitch; + for (x = 0; x < width; x++ ) + { + LONG color = (*Source++); + /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */ + /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */ + /* R */ Dest[2] = (color & 0xff) + 128; /* U */ + /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */ + Dest += 4; + } + } +} + +static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const DWORD *Source; + unsigned short *Dest; + UINT outpitch = (pitch * 3)/2; + + for(y = 0; y < height; y++) + { + Source = (const DWORD *)(src + y * pitch); + Dest = (unsigned short *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) + { + DWORD color = (*Source++); + /* B */ Dest[0] = 0xffff; + /* G */ Dest[1] = (color >> 16) + 32768; /* V */ + /* R */ Dest[2] = (color ) + 32768; /* U */ + Dest += 3; + } + } +} + +static void convert_r16g16(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const WORD *Source; + WORD *Dest; + UINT outpitch = (pitch * 3)/2; + + for(y = 0; y < height; y++) + { + Source = (const WORD *)(src + y * pitch); + Dest = (WORD *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) + { + WORD green = (*Source++); + WORD red = (*Source++); + Dest[0] = green; + Dest[1] = red; + /* Strictly speaking not correct for R16G16F, but it doesn't matter because the + * shader overwrites it anyway + */ + Dest[2] = 0xffff; + Dest += 3; + } + } +} + +static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + const float *Source; + float *Dest; + UINT outpitch = (pitch * 3)/2; + + for(y = 0; y < height; y++) + { + Source = (const float *)(src + y * pitch); + Dest = (float *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) + { + float green = (*Source++); + float red = (*Source++); + Dest[0] = green; + Dest[1] = red; + Dest[2] = 1.0f; + Dest += 3; + } + } +} + +static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + UINT outpitch = pitch * 2; + + for (y = 0; y < height; ++y) + { + const WORD *source = (const WORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + /* The depth data is normalized, so needs to be scaled, + * the stencil data isn't. Scale depth data by + * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */ + WORD d15 = source[x] >> 1; + DWORD d24 = (d15 << 9) + (d15 >> 6); + dest[x] = (d24 << 8) | (source[x] & 0x1); + } + } +} + +static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * pitch); + + for (x = 0; x < width; ++x) + { + /* Just need to clear out the X4 part. */ + dest[x] = source[x] & ~0xf0; + } + } +} + +static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height) +{ + unsigned int x, y; + UINT outpitch = pitch * 2; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + float *dest_f = (float *)(dst + y * outpitch); + DWORD *dest_s = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8); + dest_s[x * 2 + 1] = source[x] & 0xff; + } + } +} + +static const struct wined3d_format_texture_info format_texture_info[] = +{ /* WINED3DFORMAT internal srgbInternal rtInternal format type flags @@ -244,289 +561,296 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = { * endian machine */ {WINED3DFMT_UYVY, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_UYVY, GL_RGB, GL_RGB, 0, - GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_APPLE, + GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_APPLE, 0, WINED3DFMT_FLAG_FILTERING, - APPLE_YCBCR_422}, + APPLE_YCBCR_422, NULL}, {WINED3DFMT_YUY2, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_YUY2, GL_RGB, GL_RGB, 0, - GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_REV_APPLE, + GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_REV_APPLE, 0, WINED3DFMT_FLAG_FILTERING, - APPLE_YCBCR_422}, + APPLE_YCBCR_422, NULL}, {WINED3DFMT_YV12, GL_ALPHA, GL_ALPHA, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, + GL_ALPHA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_DXT1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - EXT_TEXTURE_COMPRESSION_S3TC}, + GL_RGBA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + EXT_TEXTURE_COMPRESSION_S3TC, NULL}, {WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - EXT_TEXTURE_COMPRESSION_S3TC}, + GL_RGBA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + EXT_TEXTURE_COMPRESSION_S3TC, NULL}, {WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - EXT_TEXTURE_COMPRESSION_S3TC}, + GL_RGBA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + EXT_TEXTURE_COMPRESSION_S3TC, NULL}, {WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - EXT_TEXTURE_COMPRESSION_S3TC}, + GL_RGBA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + EXT_TEXTURE_COMPRESSION_S3TC, NULL}, {WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - EXT_TEXTURE_COMPRESSION_S3TC}, + GL_RGBA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + EXT_TEXTURE_COMPRESSION_S3TC, NULL}, /* IEEE formats */ {WINED3DFMT_R32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0, - GL_RED, GL_FLOAT, + GL_RED, GL_FLOAT, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + ARB_TEXTURE_FLOAT, NULL}, {WINED3DFMT_R32_FLOAT, GL_R32F, GL_R32F, 0, - GL_RED, GL_FLOAT, + GL_RED, GL_FLOAT, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_RG}, + ARB_TEXTURE_RG, NULL}, {WINED3DFMT_R32G32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0, - GL_RGB, GL_FLOAT, + GL_RGB, GL_FLOAT, 12, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + ARB_TEXTURE_FLOAT, &convert_r32g32_float}, {WINED3DFMT_R32G32_FLOAT, GL_RG32F, GL_RG32F, 0, - GL_RG, GL_FLOAT, + GL_RG, GL_FLOAT, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_RG}, + ARB_TEXTURE_RG, NULL}, {WINED3DFMT_R32G32B32A32_FLOAT, GL_RGBA32F_ARB, GL_RGBA32F_ARB, 0, - GL_RGBA, GL_FLOAT, - WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + GL_RGBA, GL_FLOAT, 0, + WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF, + ARB_TEXTURE_FLOAT, NULL}, /* Float */ {WINED3DFMT_R16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0, - GL_RED, GL_HALF_FLOAT_ARB, + GL_RED, GL_HALF_FLOAT_ARB, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + ARB_TEXTURE_FLOAT, NULL}, {WINED3DFMT_R16_FLOAT, GL_R16F, GL_R16F, 0, - GL_RED, GL_HALF_FLOAT_ARB, + GL_RED, GL_HALF_FLOAT_ARB, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_RG}, + ARB_TEXTURE_RG, NULL}, {WINED3DFMT_R16G16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0, - GL_RGB, GL_HALF_FLOAT_ARB, + GL_RGB, GL_HALF_FLOAT_ARB, 6, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + ARB_TEXTURE_FLOAT, &convert_r16g16}, {WINED3DFMT_R16G16_FLOAT, GL_RG16F, GL_RG16F, 0, - GL_RG, GL_HALF_FLOAT_ARB, + GL_RG, GL_HALF_FLOAT_ARB, 0, WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_RG}, + ARB_TEXTURE_RG, NULL}, {WINED3DFMT_R16G16B16A16_FLOAT, GL_RGBA16F_ARB, GL_RGBA16F_ARB, 0, - GL_RGBA, GL_HALF_FLOAT_ARB, + GL_RGBA, GL_HALF_FLOAT_ARB, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET, - ARB_TEXTURE_FLOAT}, + ARB_TEXTURE_FLOAT, NULL}, /* Palettized formats */ {WINED3DFMT_P8_UINT, GL_RGBA, GL_RGBA, 0, - GL_RGBA, GL_UNSIGNED_BYTE, + GL_ALPHA, GL_UNSIGNED_BYTE, 0, 0, - ARB_FRAGMENT_PROGRAM}, + ARB_FRAGMENT_PROGRAM, NULL}, {WINED3DFMT_P8_UINT, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, 0, - GL_COLOR_INDEX, GL_UNSIGNED_BYTE, + GL_COLOR_INDEX, GL_UNSIGNED_BYTE, 0, 0, - EXT_PALETTED_TEXTURE}, + EXT_PALETTED_TEXTURE, NULL}, /* Standard ARGB formats */ {WINED3DFMT_B8G8R8_UNORM, GL_RGB8, GL_RGB8, 0, - GL_BGR, GL_UNSIGNED_BYTE, + GL_BGR, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B8G8R8A8_UNORM, GL_RGBA8, GL_SRGB8_ALPHA8_EXT, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, - WINED3D_GL_EXT_NONE}, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET + | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B8G8R8X8_UNORM, GL_RGB8, GL_SRGB8_EXT, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, - WINED3D_GL_EXT_NONE}, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET + | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B5G6R5_UNORM, GL_RGB5, GL_RGB5, GL_RGB8, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B5G5R5X1_UNORM, GL_RGB5, GL_RGB5_A1, 0, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B5G5R5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, 0, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B4G4R4A4_UNORM, GL_RGBA4, GL_SRGB8_ALPHA8_EXT, 0, - GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B2G3R3_UNORM, GL_R3_G3_B2, GL_R3_G3_B2, 0, - GL_RGB, GL_UNSIGNED_BYTE_3_3_2, + GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_A8_UNORM, GL_ALPHA8, GL_ALPHA8, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, + GL_ALPHA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_B4G4R4X4_UNORM, GL_RGB4, GL_RGB4, 0, - GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, + GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, 0, - GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, + GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, 0, - GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, + GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_R8G8B8X8_UNORM, GL_RGB8, GL_RGB8, 0, - GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, + GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_R16G16_UNORM, GL_RGB16, GL_RGB16, GL_RGBA16, - GL_RGB, GL_UNSIGNED_SHORT, + GL_RGB, GL_UNSIGNED_SHORT, 6, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, &convert_r16g16}, {WINED3DFMT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, 0, - GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, + GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_R16G16B16A16_UNORM, GL_RGBA16, GL_RGBA16, 0, - GL_RGBA, GL_UNSIGNED_SHORT, + GL_RGBA, GL_UNSIGNED_SHORT, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, /* Luminance */ {WINED3DFMT_L8_UNORM, GL_LUMINANCE8, GL_SLUMINANCE8_EXT, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_L8A8_UNORM, GL_LUMINANCE8_ALPHA8, GL_SLUMINANCE8_ALPHA8_EXT, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_L4A4_UNORM, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE4_ALPHA4, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 2, 0, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, &convert_l4a4_unorm}, /* Bump mapping stuff */ {WINED3DFMT_R8G8_SNORM, GL_RGB8, GL_RGB8, 0, - GL_BGR, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_BGR, GL_UNSIGNED_BYTE, 3, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + WINED3D_GL_EXT_NONE, &convert_r8g8_snorm}, {WINED3DFMT_R8G8_SNORM, GL_DSDT8_NV, GL_DSDT8_NV, 0, - GL_DSDT_NV, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - NV_TEXTURE_SHADER}, + GL_DSDT_NV, GL_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + NV_TEXTURE_SHADER, NULL}, {WINED3DFMT_R5G5_SNORM_L6_UNORM, GL_RGB5, GL_RGB5, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + WINED3D_GL_EXT_NONE, &convert_r5g5_snorm_l6_unorm}, {WINED3DFMT_R5G5_SNORM_L6_UNORM, GL_DSDT8_MAG8_NV, GL_DSDT8_MAG8_NV, 0, - GL_DSDT_MAG_NV, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - NV_TEXTURE_SHADER}, + GL_DSDT_MAG_NV, GL_BYTE, 3, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + NV_TEXTURE_SHADER, &convert_r5g5_snorm_l6_unorm_nv}, {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, GL_RGB8, GL_RGB8, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + WINED3D_GL_EXT_NONE, &convert_r8g8_snorm_l8x8_unorm}, {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, GL_DSDT8_MAG8_INTENSITY8_NV, GL_DSDT8_MAG8_INTENSITY8_NV, 0, - GL_DSDT_MAG_VIB_NV, GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - NV_TEXTURE_SHADER}, + GL_DSDT_MAG_VIB_NV, GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, 4, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + NV_TEXTURE_SHADER, &convert_r8g8_snorm_l8x8_unorm_nv}, {WINED3DFMT_R8G8B8A8_SNORM, GL_RGBA8, GL_RGBA8, 0, - GL_BGRA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_BGRA, GL_UNSIGNED_BYTE, 4, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + WINED3D_GL_EXT_NONE, &convert_r8g8b8a8_snorm}, {WINED3DFMT_R8G8B8A8_SNORM, GL_SIGNED_RGBA8_NV, GL_SIGNED_RGBA8_NV, 0, - GL_RGBA, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - NV_TEXTURE_SHADER}, + GL_RGBA, GL_BYTE, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + NV_TEXTURE_SHADER, NULL}, {WINED3DFMT_R16G16_SNORM, GL_RGB16, GL_RGB16, 0, - GL_BGR, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + GL_BGR, GL_UNSIGNED_SHORT, 6, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + WINED3D_GL_EXT_NONE, &convert_r16g16_snorm}, {WINED3DFMT_R16G16_SNORM, GL_SIGNED_HILO16_NV, GL_SIGNED_HILO16_NV, 0, - GL_HILO_NV, GL_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - NV_TEXTURE_SHADER}, + GL_HILO_NV, GL_SHORT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP, + NV_TEXTURE_SHADER, NULL}, /* Depth stencil formats */ {WINED3DFMT_D16_LOCKABLE, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_D32_UNORM, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - EXT_PACKED_DEPTH_STENCIL}, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + EXT_PACKED_DEPTH_STENCIL, &convert_s1_uint_d15_unorm}, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - ARB_FRAMEBUFFER_OBJECT}, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + ARB_FRAMEBUFFER_OBJECT, &convert_s1_uint_d15_unorm}, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH + | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - EXT_PACKED_DEPTH_STENCIL}, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH + | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + EXT_PACKED_DEPTH_STENCIL, NULL}, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - ARB_FRAMEBUFFER_OBJECT}, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH + | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + ARB_FRAMEBUFFER_OBJECT, NULL}, {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH + | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - EXT_PACKED_DEPTH_STENCIL}, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + EXT_PACKED_DEPTH_STENCIL, &convert_s4x4_uint_d24_unorm}, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, - GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - ARB_FRAMEBUFFER_OBJECT}, + GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + ARB_FRAMEBUFFER_OBJECT, &convert_s4x4_uint_d24_unorm}, {WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_TEXTURE}, + GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH + | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_TEXTURE, NULL}, {WINED3DFMT_L16_UNORM, GL_LUMINANCE16, GL_LUMINANCE16, 0, - GL_LUMINANCE, GL_UNSIGNED_SHORT, + GL_LUMINANCE, GL_UNSIGNED_SHORT, 0, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, - WINED3D_GL_EXT_NONE}, + WINED3D_GL_EXT_NONE, NULL}, {WINED3DFMT_D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, 0, - GL_DEPTH_COMPONENT, GL_FLOAT, - WINED3DFMT_FLAG_DEPTH, - ARB_DEPTH_BUFFER_FLOAT}, + GL_DEPTH_COMPONENT, GL_FLOAT, 0, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_BUFFER_FLOAT, NULL}, {WINED3DFMT_S8_UINT_D24_FLOAT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, 0, - GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - ARB_DEPTH_BUFFER_FLOAT}, + GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, + ARB_DEPTH_BUFFER_FLOAT, &convert_s8_uint_d24_float}, /* Vendor-specific formats */ {WINED3DFMT_ATI2N, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, 0, - ATI_TEXTURE_COMPRESSION_3DC}, + ATI_TEXTURE_COMPRESSION_3DC, NULL}, {WINED3DFMT_ATI2N, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, 0, - EXT_TEXTURE_COMPRESSION_RGTC}, + EXT_TEXTURE_COMPRESSION_RGTC, NULL}, }; static inline int getFmtIdx(WINED3DFORMAT fmt) { @@ -560,7 +884,7 @@ static BOOL init_format_base_info(struct wined3d_gl_info *gl_info) for (i = 0; i < format_count; ++i) { - struct GlPixelFormatDesc *desc = &gl_info->gl_formats[i]; + struct wined3d_format_desc *desc = &gl_info->gl_formats[i]; desc->format = formats[i].format; desc->red_mask = formats[i].redMask; desc->green_mask = formats[i].greenMask; @@ -595,7 +919,7 @@ static BOOL init_format_compression_info(struct wined3d_gl_info *gl_info) for (i = 0; i < (sizeof(format_compression_info) / sizeof(*format_compression_info)); ++i) { - struct GlPixelFormatDesc *format_desc; + struct wined3d_format_desc *format_desc; int fmt_idx = getFmtIdx(format_compression_info[i].format); if (fmt_idx == -1) @@ -616,7 +940,7 @@ static BOOL init_format_compression_info(struct wined3d_gl_info *gl_info) } /* Context activation is done by the caller. */ -static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct GlPixelFormatDesc *format_desc) +static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format_desc *format_desc) { /* Check if the default internal format is supported as a frame buffer * target, otherwise fall back to the render target internal. @@ -755,7 +1079,7 @@ static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info) for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { - struct GlPixelFormatDesc *desc = &gl_info->gl_formats[i]; + struct wined3d_format_desc *desc = &gl_info->gl_formats[i]; if (!desc->glInternal) continue; @@ -798,29 +1122,33 @@ static BOOL init_format_texture_info(struct wined3d_gl_info *gl_info) { unsigned int i; - for (i = 0; i < sizeof(gl_formats_template) / sizeof(gl_formats_template[0]); ++i) + for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i) { - int fmt_idx = getFmtIdx(gl_formats_template[i].fmt); - struct GlPixelFormatDesc *desc; + int fmt_idx = getFmtIdx(format_texture_info[i].format); + struct wined3d_format_desc *desc; if (fmt_idx == -1) { ERR("Format %s (%#x) not found.\n", - debug_d3dformat(gl_formats_template[i].fmt), gl_formats_template[i].fmt); + debug_d3dformat(format_texture_info[i].format), format_texture_info[i].format); return FALSE; } - if (!gl_info->supported[gl_formats_template[i].extension]) continue; + if (!gl_info->supported[format_texture_info[i].extension]) continue; desc = &gl_info->gl_formats[fmt_idx]; - desc->glInternal = gl_formats_template[i].glInternal; - desc->glGammaInternal = gl_formats_template[i].glGammaInternal; - desc->rtInternal = gl_formats_template[i].rtInternal; - desc->glFormat = gl_formats_template[i].glFormat; - desc->glType = gl_formats_template[i].glType; + desc->glInternal = format_texture_info[i].gl_internal; + desc->glGammaInternal = format_texture_info[i].gl_srgb_internal; + desc->rtInternal = format_texture_info[i].gl_rt_internal; + desc->glFormat = format_texture_info[i].gl_format; + desc->glType = format_texture_info[i].gl_type; desc->color_fixup = COLOR_FIXUP_IDENTITY; - desc->Flags |= gl_formats_template[i].Flags; + desc->Flags |= format_texture_info[i].flags; desc->heightscale = 1.0f; + + /* Texture conversion stuff */ + desc->convert = format_texture_info[i].convert; + desc->conv_byte_count = format_texture_info[i].conv_byte_count; } return TRUE; @@ -938,6 +1266,7 @@ static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal) static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor) { + struct wined3d_format_desc *desc; unsigned int fmt_idx, i; WINED3DFORMAT fmts16[] = { WINED3DFMT_R16_FLOAT, @@ -945,7 +1274,6 @@ static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3 WINED3DFMT_R16G16B16A16_FLOAT, }; BOOL filtered; - struct GlPixelFormatDesc *desc; if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) { @@ -1043,6 +1371,7 @@ static void apply_format_fixups(struct wined3d_gl_info *gl_info) idx = getFmtIdx(WINED3DFMT_R8G8_SNORM); gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE); + idx = getFmtIdx(WINED3DFMT_R16G16_SNORM); gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE); @@ -1098,8 +1427,11 @@ static void apply_format_fixups(struct wined3d_gl_info *gl_info) gl_info->gl_formats[idx].heightscale = 1.5f; gl_info->gl_formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12); - idx = getFmtIdx(WINED3DFMT_P8_UINT); - gl_info->gl_formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8); + if (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM]) + { + idx = getFmtIdx(WINED3DFMT_P8_UINT); + gl_info->gl_formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8); + } if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA]) { @@ -1125,7 +1457,7 @@ static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info) for (i = 0; i < (sizeof(format_vertex_info) / sizeof(*format_vertex_info)); ++i) { - struct GlPixelFormatDesc *format_desc; + struct wined3d_format_desc *format_desc; int fmt_idx = getFmtIdx(format_vertex_info[i].format); if (fmt_idx == -1) @@ -1182,7 +1514,7 @@ fail: return FALSE; } -const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, const struct wined3d_gl_info *gl_info) +const struct wined3d_format_desc *getFormatDescEntry(WINED3DFORMAT fmt, const struct wined3d_gl_info *gl_info) { int idx = getFmtIdx(fmt); @@ -1485,9 +1817,7 @@ const char* debug_d3dprimitivetype(WINED3DPRIMITIVETYPE PrimitiveType) { const char* debug_d3drenderstate(DWORD state) { switch (state) { #define D3DSTATE_TO_STR(u) case u: return #u - D3DSTATE_TO_STR(WINED3DRS_TEXTUREHANDLE ); D3DSTATE_TO_STR(WINED3DRS_ANTIALIAS ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESS ); D3DSTATE_TO_STR(WINED3DRS_TEXTUREPERSPECTIVE ); D3DSTATE_TO_STR(WINED3DRS_WRAPU ); D3DSTATE_TO_STR(WINED3DRS_WRAPV ); @@ -1501,11 +1831,8 @@ const char* debug_d3drenderstate(DWORD state) { D3DSTATE_TO_STR(WINED3DRS_ZWRITEENABLE ); D3DSTATE_TO_STR(WINED3DRS_ALPHATESTENABLE ); D3DSTATE_TO_STR(WINED3DRS_LASTPIXEL ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREMAG ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREMIN ); D3DSTATE_TO_STR(WINED3DRS_SRCBLEND ); D3DSTATE_TO_STR(WINED3DRS_DESTBLEND ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREMAPBLEND ); D3DSTATE_TO_STR(WINED3DRS_CULLMODE ); D3DSTATE_TO_STR(WINED3DRS_ZFUNC ); D3DSTATE_TO_STR(WINED3DRS_ALPHAREF ); @@ -1526,9 +1853,6 @@ const char* debug_d3drenderstate(DWORD state) { D3DSTATE_TO_STR(WINED3DRS_STIPPLEENABLE ); D3DSTATE_TO_STR(WINED3DRS_EDGEANTIALIAS ); D3DSTATE_TO_STR(WINED3DRS_COLORKEYENABLE ); - D3DSTATE_TO_STR(WINED3DRS_BORDERCOLOR ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESSU ); - D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESSV ); D3DSTATE_TO_STR(WINED3DRS_MIPMAPLODBIAS ); D3DSTATE_TO_STR(WINED3DRS_ZBIAS ); D3DSTATE_TO_STR(WINED3DRS_RANGEFOGENABLE ); @@ -1544,38 +1868,6 @@ const char* debug_d3drenderstate(DWORD state) { D3DSTATE_TO_STR(WINED3DRS_STENCILMASK ); D3DSTATE_TO_STR(WINED3DRS_STENCILWRITEMASK ); D3DSTATE_TO_STR(WINED3DRS_TEXTUREFACTOR ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN00 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN01 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN02 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN03 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN04 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN05 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN06 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN07 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN08 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN09 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN10 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN11 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN12 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN13 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN14 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN15 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN16 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN17 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN18 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN19 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN20 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN21 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN22 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN23 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN24 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN25 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN26 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN27 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN28 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN29 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN30 ); - D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN31 ); D3DSTATE_TO_STR(WINED3DRS_WRAP0 ); D3DSTATE_TO_STR(WINED3DRS_WRAP1 ); D3DSTATE_TO_STR(WINED3DRS_WRAP2 ); @@ -2125,7 +2417,7 @@ unsigned int count_bits(unsigned int mask) /* Helper function for retrieving color info for ChoosePixelFormat and wglChoosePixelFormatARB. * The later function requires individual color components. */ -BOOL getColorBits(const struct GlPixelFormatDesc *format_desc, +BOOL getColorBits(const struct wined3d_format_desc *format_desc, short *redSize, short *greenSize, short *blueSize, short *alphaSize, short *totalSize) { TRACE("fmt: %s\n", debug_d3dformat(format_desc->format)); @@ -2162,7 +2454,7 @@ BOOL getColorBits(const struct GlPixelFormatDesc *format_desc, } /* Helper function for retrieving depth/stencil info for ChoosePixelFormat and wglChoosePixelFormatARB */ -BOOL getDepthStencilBits(const struct GlPixelFormatDesc *format_desc, short *depthSize, short *stencilSize) +BOOL getDepthStencilBits(const struct wined3d_format_desc *format_desc, short *depthSize, short *stencilSize) { TRACE("fmt: %s\n", debug_d3dformat(format_desc->format)); switch(format_desc->format) @@ -2190,6 +2482,115 @@ BOOL getDepthStencilBits(const struct GlPixelFormatDesc *format_desc, short *dep return TRUE; } +DWORD color_convert_argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) +{ + unsigned int r, g, b, a; + DWORD ret; + + if (destfmt == WINED3DFMT_B8G8R8A8_UNORM + || destfmt == WINED3DFMT_B8G8R8X8_UNORM + || destfmt == WINED3DFMT_B8G8R8_UNORM) + return color; + + TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt)); + + a = (color & 0xff000000) >> 24; + r = (color & 0x00ff0000) >> 16; + g = (color & 0x0000ff00) >> 8; + b = (color & 0x000000ff) >> 0; + + switch(destfmt) + { + case WINED3DFMT_B5G6R5_UNORM: + if(r == 0xff && g == 0xff && b == 0xff) return 0xffff; + r = (r * 32) / 256; + g = (g * 64) / 256; + b = (b * 32) / 256; + ret = r << 11; + ret |= g << 5; + ret |= b; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_B5G5R5X1_UNORM: + case WINED3DFMT_B5G5R5A1_UNORM: + a = (a * 2) / 256; + r = (r * 32) / 256; + g = (g * 32) / 256; + b = (b * 32) / 256; + ret = a << 15; + ret |= r << 10; + ret |= g << 5; + ret |= b << 0; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_A8_UNORM: + TRACE("Returning %08x\n", a); + return a; + + case WINED3DFMT_B4G4R4X4_UNORM: + case WINED3DFMT_B4G4R4A4_UNORM: + a = (a * 16) / 256; + r = (r * 16) / 256; + g = (g * 16) / 256; + b = (b * 16) / 256; + ret = a << 12; + ret |= r << 8; + ret |= g << 4; + ret |= b << 0; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_B2G3R3_UNORM: + r = (r * 8) / 256; + g = (g * 8) / 256; + b = (b * 4) / 256; + ret = r << 5; + ret |= g << 2; + ret |= b << 0; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_R8G8B8X8_UNORM: + case WINED3DFMT_R8G8B8A8_UNORM: + ret = a << 24; + ret |= b << 16; + ret |= g << 8; + ret |= r << 0; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_B10G10R10A2_UNORM: + a = (a * 4) / 256; + r = (r * 1024) / 256; + g = (g * 1024) / 256; + b = (b * 1024) / 256; + ret = a << 30; + ret |= r << 20; + ret |= g << 10; + ret |= b << 0; + TRACE("Returning %08x\n", ret); + return ret; + + case WINED3DFMT_R10G10B10A2_UNORM: + a = (a * 4) / 256; + r = (r * 1024) / 256; + g = (g * 1024) / 256; + b = (b * 1024) / 256; + ret = a << 30; + ret |= b << 20; + ret |= g << 10; + ret |= r << 0; + TRACE("Returning %08x\n", ret); + return ret; + + default: + FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt)); + return 0; + } +} + /* DirectDraw stuff */ WINED3DFORMAT pixelformat_for_depth(DWORD depth) { switch(depth) { @@ -2258,147 +2659,6 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) { return size; } -/*********************************************************************** - * CalculateTexRect - * - * Calculates the dimensions of the opengl texture used for blits. - * Handled oversized opengl textures and updates the source rectangle - * accordingly - * - * Params: - * This: Surface to operate on - * Rect: Requested rectangle - * - * Returns: - * TRUE if the texture part can be loaded, - * FALSE otherwise - * - *********************************************************************/ -BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]) -{ - const struct wined3d_gl_info *gl_info = &This->resource.device->adapter->gl_info; - int x1 = Rect->left, x2 = Rect->right; - int y1 = Rect->top, y2 = Rect->bottom; - GLint maxSize = gl_info->limits.texture_size; - - TRACE("(%p)->(%d,%d)-(%d,%d)\n", This, - Rect->left, Rect->top, Rect->right, Rect->bottom); - - /* The sizes might be reversed */ - if(Rect->left > Rect->right) { - x1 = Rect->right; - x2 = Rect->left; - } - if(Rect->top > Rect->bottom) { - y1 = Rect->bottom; - y2 = Rect->top; - } - - /* No oversized texture? This is easy */ - if(!(This->Flags & SFLAG_OVERSIZE)) { - /* Which rect from the texture do I need? */ - if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) - { - glTexCoord[0] = (float) Rect->left; - glTexCoord[2] = (float) Rect->top; - glTexCoord[1] = (float) Rect->right; - glTexCoord[3] = (float) Rect->bottom; - } else { - glTexCoord[0] = (float) Rect->left / (float) This->pow2Width; - glTexCoord[2] = (float) Rect->top / (float) This->pow2Height; - glTexCoord[1] = (float) Rect->right / (float) This->pow2Width; - glTexCoord[3] = (float) Rect->bottom / (float) This->pow2Height; - } - - return TRUE; - } else { - /* Check if we can succeed at all */ - if( (x2 - x1) > maxSize || - (y2 - y1) > maxSize ) { - TRACE("Requested rectangle is too large for gl\n"); - return FALSE; - } - - /* A part of the texture has to be picked. First, check if - * some texture part is loaded already, if yes try to re-use it. - * If the texture is dirty, or the part can't be used, - * re-position the part to load - */ - if(This->Flags & SFLAG_INTEXTURE) { - if(This->glRect.left <= x1 && This->glRect.right >= x2 && - This->glRect.top <= y1 && This->glRect.bottom >= x2 ) { - /* Ok, the rectangle is ok, re-use it */ - TRACE("Using existing gl Texture\n"); - } else { - /* Rectangle is not ok, dirtify the texture to reload it */ - TRACE("Dirtifying texture to force reload\n"); - This->Flags &= ~SFLAG_INTEXTURE; - } - } - - /* Now if we are dirty(no else if!) */ - if(!(This->Flags & SFLAG_INTEXTURE)) { - /* Set the new rectangle. Use the following strategy: - * 1) Use as big textures as possible. - * 2) Place the texture part in the way that the requested - * part is in the middle of the texture(well, almost) - * 3) If the texture is moved over the edges of the - * surface, replace it nicely - * 4) If the coord is not limiting the texture size, - * use the whole size - */ - if((This->pow2Width) > maxSize) { - This->glRect.left = x1 - maxSize / 2; - if(This->glRect.left < 0) { - This->glRect.left = 0; - } - This->glRect.right = This->glRect.left + maxSize; - if(This->glRect.right > This->currentDesc.Width) { - This->glRect.right = This->currentDesc.Width; - This->glRect.left = This->glRect.right - maxSize; - } - } else { - This->glRect.left = 0; - This->glRect.right = This->pow2Width; - } - - if (This->pow2Height > maxSize) - { - This->glRect.top = x1 - gl_info->limits.texture_size / 2; - if(This->glRect.top < 0) This->glRect.top = 0; - This->glRect.bottom = This->glRect.left + maxSize; - if(This->glRect.bottom > This->currentDesc.Height) { - This->glRect.bottom = This->currentDesc.Height; - This->glRect.top = This->glRect.bottom - maxSize; - } - } else { - This->glRect.top = 0; - This->glRect.bottom = This->pow2Height; - } - TRACE("(%p): Using rect (%d,%d)-(%d,%d)\n", This, - This->glRect.left, This->glRect.top, This->glRect.right, This->glRect.bottom); - } - - /* Re-calculate the rect to draw */ - Rect->left -= This->glRect.left; - Rect->right -= This->glRect.left; - Rect->top -= This->glRect.top; - Rect->bottom -= This->glRect.top; - - /* Get the gl coordinates. The gl rectangle is a power of 2, eigher the max size, - * or the pow2Width / pow2Height of the surface. - * - * Can never be GL_TEXTURE_RECTANGLE_ARB because oversized surfaces are always set up - * as regular GL_TEXTURE_2D. - */ - glTexCoord[0] = (float) Rect->left / (float) (This->glRect.right - This->glRect.left); - glTexCoord[2] = (float) Rect->top / (float) (This->glRect.bottom - This->glRect.top); - glTexCoord[1] = (float) Rect->right / (float) (This->glRect.right - This->glRect.left); - glTexCoord[3] = (float) Rect->bottom / (float) (This->glRect.bottom - This->glRect.top); - } - return TRUE; -} - void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings, BOOL ignore_textype) { #define ARG1 0x01 #define ARG2 0x02 @@ -2518,8 +2778,8 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) { - IWineD3DSurfaceImpl *surf; - surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0]; + IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0]; if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask) { @@ -2826,8 +3086,10 @@ UINT wined3d_log2i(UINT32 x) * and the user preferences in wined3d_settings. */ void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, int *vs_selected) { + BOOL glsl = wined3d_settings.glslRequested && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 20); + if (wined3d_settings.vs_mode == VS_NONE) *vs_selected = SHADER_NONE; - else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) + else if (gl_info->supported[ARB_VERTEX_SHADER] && glsl) { /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB @@ -2839,7 +3101,7 @@ void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, else *vs_selected = SHADER_NONE; if (wined3d_settings.ps_mode == PS_NONE) *ps_selected = SHADER_NONE; - else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) *ps_selected = SHADER_GLSL; + else if (gl_info->supported[ARB_FRAGMENT_SHADER] && glsl) *ps_selected = SHADER_GLSL; else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) *ps_selected = SHADER_ARB; else if (gl_info->supported[ATI_FRAGMENT_SHADER]) *ps_selected = SHADER_ATI; else *ps_selected = SHADER_NONE; diff --git a/reactos/dll/directx/wine/wined3d/view.c b/reactos/dll/directx/wine/wined3d/view.c index bbf0f5f65c1..0c9919dd14c 100644 --- a/reactos/dll/directx/wine/wined3d/view.c +++ b/reactos/dll/directx/wine/wined3d/view.c @@ -97,7 +97,7 @@ static HRESULT STDMETHODCALLTYPE rendertarget_view_GetResource(IWineD3DRendertar return WINED3D_OK; } -const struct IWineD3DRendertargetViewVtbl wined3d_rendertarget_view_vtbl = +static const struct IWineD3DRendertargetViewVtbl wined3d_rendertarget_view_vtbl = { /* IUnknown methods */ rendertarget_view_QueryInterface, @@ -108,3 +108,13 @@ const struct IWineD3DRendertargetViewVtbl wined3d_rendertarget_view_vtbl = /* IWineD3DRendertargetView methods */ rendertarget_view_GetResource, }; + +void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view, + IWineD3DResource *resource, IUnknown *parent) +{ + view->vtbl = &wined3d_rendertarget_view_vtbl; + view->refcount = 1; + IWineD3DResource_AddRef(resource); + view->resource = resource; + view->parent = parent; +} diff --git a/reactos/dll/directx/wine/wined3d/volume.c b/reactos/dll/directx/wine/wined3d/volume.c index 8e19ee9c763..42e61e68d22 100644 --- a/reactos/dll/directx/wine/wined3d/volume.c +++ b/reactos/dll/directx/wine/wined3d/volume.c @@ -25,7 +25,6 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); -#define GLINFO_LOCATION This->resource.device->adapter->gl_info /* Context activation is done by the caller. */ static void volume_bind_and_dirtify(IWineD3DVolume *iface) { @@ -313,9 +312,11 @@ static HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IWi } /* Context activation is done by the caller. */ -static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, int gl_level, BOOL srgb_mode) { - IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; - const struct GlPixelFormatDesc *glDesc = This->resource.format_desc; +static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, int gl_level, BOOL srgb_mode) +{ + IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->resource.device->adapter->gl_info; + const struct wined3d_format_desc *glDesc = This->resource.format_desc; TRACE("(%p) : level %u, format %s (0x%08x)\n", This, gl_level, debug_d3dformat(glDesc->format), glDesc->format); @@ -386,7 +387,7 @@ HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); HRESULT hr; if (!gl_info->supported[EXT_TEXTURE3D]) diff --git a/reactos/dll/directx/wine/wined3d/volumetexture.c b/reactos/dll/directx/wine/wined3d/volumetexture.c index 14ca72fcd49..9fccb2b8936 100644 --- a/reactos/dll/directx/wine/wined3d/volumetexture.c +++ b/reactos/dll/directx/wine/wined3d/volumetexture.c @@ -39,7 +39,7 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE TRACE("(%p) : About to load texture.\n", This); - if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) context = context_acquire(device, NULL); else if (gl_info->supported[EXT_TEXTURE_SRGB] && This->baseTexture.bindCount > 0) { srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; @@ -51,17 +51,19 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE * since the last load then reload the volumes. */ if (This->baseTexture.texture_rgb.dirty) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i]; + IWineD3DVolume_LoadTexture(volume, i, srgb_mode); } } else if (srgb_was_toggled) { - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - volume_add_dirty_box(This->volumes[i], NULL); - IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i]; + volume_add_dirty_box(volume, NULL); + IWineD3DVolume_LoadTexture(volume, i, srgb_mode); } } else @@ -81,9 +83,9 @@ static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This) TRACE("(%p) : Cleaning up.\n", This); - for (i = 0; i < This->baseTexture.levels; ++i) + for (i = 0; i < This->baseTexture.level_count; ++i) { - IWineD3DVolume *volume = This->volumes[i]; + IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i]; if (volume) { @@ -172,8 +174,9 @@ static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface * surface before, this one will be a NOP and vice versa. Unloading an unloaded * surface is fine */ - for (i = 0; i < This->baseTexture.levels; i++) { - IWineD3DVolume_UnLoad(This->volumes[i]); + for (i = 0; i < This->baseTexture.level_count; ++i) + { + IWineD3DVolume_UnLoad((IWineD3DVolume *)This->baseTexture.sub_resources[i]); } basetexture_unload((IWineD3DBaseTexture *)iface); @@ -250,65 +253,95 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *if /* ******************************************* IWineD3DVolumeTexture IWineD3DVolumeTexture parts follow ******************************************* */ -static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTexture *iface, UINT Level,WINED3DVOLUME_DESC *pDesc) { - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - if (Level < This->baseTexture.levels) { - TRACE("(%p) Level (%d)\n", This, Level); - return IWineD3DVolume_GetDesc(This->volumes[Level], pDesc); - } else { - WARN("(%p) Level (%d)\n", This, Level); +static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTexture *iface, + UINT level, WINED3DVOLUME_DESC *desc) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DVolume *volume; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); + + if (!(volume = (IWineD3DVolume *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return WINED3D_OK; + + return IWineD3DVolume_GetDesc(volume, desc); } -static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTexture *iface, UINT Level, IWineD3DVolume** ppVolumeLevel) { - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - if (Level < This->baseTexture.levels) { - *ppVolumeLevel = This->volumes[Level]; - IWineD3DVolume_AddRef(*ppVolumeLevel); - TRACE("(%p) -> level(%d) returning volume@%p\n", This, Level, *ppVolumeLevel); - } else { - WARN("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - return WINED3DERR_INVALIDCALL; + +static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTexture *iface, + UINT level, IWineD3DVolume **volume) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DVolume *v; + + TRACE("iface %p, level %u, volume %p.\n", iface, level, volume); + + if (!(v = (IWineD3DVolume *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return WINED3D_OK; + IWineD3DVolume_AddRef(v); + *volume = v; + + TRACE("Returning volume %p.\n", *volume); + + return WINED3D_OK; } -static HRESULT WINAPI IWineD3DVolumeTextureImpl_LockBox(IWineD3DVolumeTexture *iface, UINT Level, WINED3DLOCKED_BOX* pLockedVolume, CONST WINED3DBOX* pBox, DWORD Flags) { - HRESULT hr; - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - if (Level < This->baseTexture.levels) { - hr = IWineD3DVolume_LockBox(This->volumes[Level], pLockedVolume, pBox, Flags); - TRACE("(%p) Level (%d) success(%u)\n", This, Level, hr); +static HRESULT WINAPI IWineD3DVolumeTextureImpl_LockBox(IWineD3DVolumeTexture *iface, + UINT level, WINED3DLOCKED_BOX *locked_box, const WINED3DBOX *box, DWORD flags) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DVolume *volume; + + TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n", + iface, level, locked_box, box, flags); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - return WINED3DERR_INVALIDCALL; + if (!(volume = (IWineD3DVolume *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + return IWineD3DVolume_LockBox(volume, locked_box, box, flags); } -static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnlockBox(IWineD3DVolumeTexture *iface, UINT Level) { - HRESULT hr; - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; +static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnlockBox(IWineD3DVolumeTexture *iface, UINT level) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DVolume *volume; - if (Level < This->baseTexture.levels) { - hr = IWineD3DVolume_UnlockBox(This->volumes[Level]); - TRACE("(%p) -> level(%d) success(%u)\n", This, Level, hr); + TRACE("iface %p, level %u.\n", iface, level); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); - return WINED3DERR_INVALIDCALL; + if (!(volume = (IWineD3DVolume *)basetexture_get_sub_resource(texture, 0, level))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; } - return hr; + + return IWineD3DVolume_UnlockBox(volume); } -static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTexture *iface, CONST WINED3DBOX* pDirtyBox) { - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - This->baseTexture.texture_rgb.dirty = TRUE; - This->baseTexture.texture_srgb.dirty = TRUE; - TRACE("(%p) : dirtyfication of volume Level (0)\n", This); - volume_add_dirty_box(This->volumes[0], pDirtyBox); +static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTexture *iface, const WINED3DBOX *dirty_box) +{ + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)iface; + IWineD3DVolume *volume; + + TRACE("iface %p, dirty_box %p.\n", iface, dirty_box); + + if (!(volume = (IWineD3DVolume *)basetexture_get_sub_resource(texture, 0, 0))) + { + WARN("Failed to get sub-resource.\n"); + return WINED3DERR_INVALIDCALL; + } + + texture->baseTexture.texture_rgb.dirty = TRUE; + texture->baseTexture.texture_srgb.dirty = TRUE; + volume_add_dirty_box(volume, dirty_box); return WINED3D_OK; } @@ -355,7 +388,7 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info); UINT tmp_w, tmp_h, tmp_d; unsigned int i; HRESULT hr; @@ -399,8 +432,8 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT texture->lpVtbl = &IWineD3DVolumeTexture_Vtbl; - hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_VOLUMETEXTURE, - device, 0, usage, format_desc, pool, parent, parent_ops); + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, 1, levels, + WINED3DRTYPE_VOLUMETEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops); if (FAILED(hr)) { WARN("Failed to initialize basetexture, returning %#x.\n", hr); @@ -418,21 +451,23 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT tmp_h = height; tmp_d = depth; - for (i = 0; i < texture->baseTexture.levels; ++i) + for (i = 0; i < texture->baseTexture.level_count; ++i) { + IWineD3DVolume *volume; + /* Create the volume. */ hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent, - tmp_w, tmp_h, tmp_d, format, pool, usage, &texture->volumes[i]); + tmp_w, tmp_h, tmp_d, format, pool, usage, &volume); if (FAILED(hr)) { ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr); - texture->volumes[i] = NULL; volumetexture_cleanup(texture); return hr; } /* Set its container to this texture. */ - IWineD3DVolume_SetContainer(texture->volumes[i], (IWineD3DBase *)texture); + IWineD3DVolume_SetContainer(volume, (IWineD3DBase *)texture); + texture->baseTexture.sub_resources[i] = (IWineD3DResourceImpl *)volume; /* Calculate the next mipmap level. */ tmp_w = max(1, tmp_w >> 1); diff --git a/reactos/dll/directx/wine/wined3d/wined3d_gl.h b/reactos/dll/directx/wine/wined3d/wined3d_gl.h index f8097d65cb9..4ece7e7df9a 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_gl.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_gl.h @@ -1754,6 +1754,7 @@ typedef enum wined3d_gl_extension ARB_SHADER_OBJECTS, ARB_SHADER_TEXTURE_LOD, ARB_SHADING_LANGUAGE_100, + ARB_SHADOW, ARB_SYNC, ARB_TEXTURE_BORDER_CLAMP, ARB_TEXTURE_COMPRESSION, @@ -1782,6 +1783,7 @@ typedef enum wined3d_gl_extension EXT_BLEND_EQUATION_SEPARATE, EXT_BLEND_FUNC_SEPARATE, EXT_BLEND_MINMAX, + EXT_DRAW_BUFFERS2, EXT_FOG_COORD, EXT_FRAMEBUFFER_BLIT, EXT_FRAMEBUFFER_MULTISAMPLE, @@ -1829,7 +1831,6 @@ typedef enum wined3d_gl_extension SGIS_GENERATE_MIPMAP, SGI_VIDEO_SYNC, /* WGL extensions */ - WGL_ARB_PBUFFER, WGL_ARB_PIXEL_FORMAT, WGL_WINE_PIXEL_FORMAT_PASSTHROUGH, /* Internally used */ @@ -2404,6 +2405,14 @@ typedef unsigned int GLhandleARB; #define GL_SHADING_LANGUAGE_VERSION_ARB 0x8b8c #endif +/* GL_ARB_shadow */ +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884c +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884d +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884e +#endif + /* GL_ARB_sync */ #ifndef GL_ARB_sync #define GL_ARB_sync 1 @@ -2959,6 +2968,15 @@ typedef void (WINE_GLAPI *PGLFNBLENDEQUATIONSEPARATEEXTPROC)(GLenum modeRGB, GLe typedef void (WINE_GLAPI *PGLFNBLENDFUNCSEPARATEEXTPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +/* GL_EXT_draw_buffers2 */ +typedef GLvoid (WINE_GLAPI *PGLFNCOLORMASKINDEXEDEXTPROC)(GLuint buffer_idx, GLboolean r, GLboolean g, + GLboolean b, GLboolean a); +typedef GLvoid (WINE_GLAPI *PGLFNGETBOOLEANINDEXEDVEXTPROC)(GLenum param, GLuint index, GLboolean *value); +typedef GLvoid (WINE_GLAPI *PGLFNGETINTEGERINDEXEDVEXTPROC)(GLenum param, GLuint index, GLint *value); +typedef GLvoid (WINE_GLAPI *PGLFNENABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef GLvoid (WINE_GLAPI *PGLFNDISABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef GLboolean (WINE_GLAPI *PGLFNISENABLEDINDEXEDEXTPROC)(GLenum target, GLuint index); + /* GL_EXT_fog_coord */ #ifndef GL_EXT_fog_coord #define GL_EXT_fog_coord 1 @@ -3680,26 +3698,6 @@ typedef const char *(WINAPI *WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc); #define WGL_SAMPLES_ARB 0x2042 #endif -/* WGL_ARB_pbuffer */ -#ifndef WGL_ARB_pbuffer -#define WGL_ARB_pbuffer 1 -#define WGL_DRAW_TO_PBUFFER_ARB 0x202d -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202e -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202f -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 -#endif -DECLARE_HANDLE(HPBUFFERARB); -typedef HPBUFFERARB (WINAPI *WINED3D_PFNWGLCREATEPBUFFERARBPROC)(HDC hDC, int iPixelFormat, - int iWidth, int iHeight, const int *piAttribList); -typedef HDC (WINAPI *WINED3D_PFNWGLGETPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer); -typedef int (WINAPI *WINED3D_PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer, HDC hDC); -typedef BOOL (WINAPI *WINED3D_PFNWGLDESTROYPBUFFERARBPROC)(HPBUFFERARB hPbuffer); -typedef BOOL (WINAPI *WINED3D_PFNWGLQUERYPBUFFERARBPROC)(HPBUFFERARB hPbuffer, int iAttribute, int *piValue); - /* WGL_ARB_pixel_format */ #ifndef WGL_ARB_pixel_format #define WGL_ARB_pixel_format 1 @@ -3930,7 +3928,7 @@ typedef BOOL (WINAPI *WINED3D_PFNWGLSETPIXELFORMATWINE)(HDC hdc, int iPixelForma glUniform3iARB, ARB_SHADER_OBJECTS, NULL) \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IARBPROC, \ glUniform4iARB, ARB_SHADER_OBJECTS, NULL) \ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, \ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FARBPROC, \ glUniform1fARB, ARB_SHADER_OBJECTS, NULL) \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, \ glUniform2fARB, ARB_SHADER_OBJECTS, NULL) \ @@ -4199,6 +4197,19 @@ typedef BOOL (WINAPI *WINED3D_PFNWGLSETPIXELFORMATWINE)(HDC hdc, int iPixelForma /* GL_EXT_blend_func_separate */ \ USE_GL_FUNC(PGLFNBLENDEQUATIONSEPARATEEXTPROC, \ glBlendEquationSeparateEXT, EXT_BLEND_EQUATION_SEPARATE, NULL) \ + /* GL_EXT_draw_buffers2 */ \ + USE_GL_FUNC(PGLFNCOLORMASKINDEXEDEXTPROC, \ + glColorMaskIndexedEXT, EXT_DRAW_BUFFERS2, NULL) \ + USE_GL_FUNC(PGLFNGETBOOLEANINDEXEDVEXTPROC, \ + glGetBooleanIndexedvEXT, EXT_DRAW_BUFFERS2, NULL) \ + USE_GL_FUNC(PGLFNGETINTEGERINDEXEDVEXTPROC, \ + glGetIntegerIndexedvEXT, EXT_DRAW_BUFFERS2, NULL) \ + USE_GL_FUNC(PGLFNENABLEINDEXEDEXTPROC, \ + glEnableIndexedEXT, EXT_DRAW_BUFFERS2, NULL) \ + USE_GL_FUNC(PGLFNDISABLEINDEXEDEXTPROC, \ + glDisableIndexedEXT, EXT_DRAW_BUFFERS2, NULL) \ + USE_GL_FUNC(PGLFNISENABLEDINDEXEDEXTPROC, \ + glIsEnabledIndexedEXT, EXT_DRAW_BUFFERS2, NULL) \ /* GL_EXT_fog_coord */ \ USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, \ glFogCoordfEXT, EXT_FOG_COORD, NULL) \ @@ -4489,11 +4500,6 @@ typedef BOOL (WINAPI *WINED3D_PFNWGLSETPIXELFORMATWINE)(HDC hdc, int iPixelForma USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB, 0, NULL) \ USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBFVARBPROC, wglGetPixelFormatAttribfvARB, 0, NULL) \ USE_GL_FUNC(WINED3D_PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLCREATEPBUFFERARBPROC, wglCreatePbufferARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLQUERYPBUFFERARBPROC, wglQueryPbufferARB, 0, NULL) \ USE_GL_FUNC(WINED3D_PFNWGLSETPIXELFORMATWINE, wglSetPixelFormatWINE, 0, NULL) #endif /* __WINE_WINED3D_GL */ diff --git a/reactos/dll/directx/wine/wined3d/wined3d_main.c b/reactos/dll/directx/wine/wined3d/wined3d_main.c index 39416e1f875..6330eba44d4 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_main.c +++ b/reactos/dll/directx/wine/wined3d/wined3d_main.c @@ -72,30 +72,31 @@ wined3d_settings_t wined3d_settings = PCI_DEVICE_NONE,/* PCI Device ID */ 0, /* The default of memory is set in FillGLCaps */ NULL, /* No wine logo by default */ - FALSE /* Disable multisampling for now due to Nvidia driver bugs which happens for some users */ + FALSE, /* Disable multisampling for now due to Nvidia driver bugs which happens for some users */ + FALSE, /* No strict draw ordering. */ }; -IWineD3D* WINAPI WineDirect3DCreate(UINT dxVersion, IUnknown *parent) { - IWineD3DImpl* object; +IWineD3D * WINAPI WineDirect3DCreate(UINT version, IUnknown *parent) +{ + IWineD3DImpl *object; + HRESULT hr; - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DImpl)); - object->lpVtbl = &IWineD3D_Vtbl; - object->dxVersion = dxVersion; - object->ref = 1; - object->parent = parent; + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Failed to allocate wined3d object memory.\n"); + return NULL; + } - if (!InitAdapters(object)) + hr = wined3d_init(object, version, parent); + if (FAILED(hr)) { - WARN("Failed to initialize direct3d adapters, Direct3D will not be available\n"); - if (dxVersion > 7) - { - ERR("Direct3D%d is not available without opengl\n", dxVersion); - HeapFree(GetProcessHeap(), 0, object); - return NULL; - } + WARN("Failed to initialize wined3d object, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return NULL; } - TRACE("Created WineD3D object @ %p for d3d%d support\n", object, dxVersion); + TRACE("Created wined3d object %p for d3d%d support.\n", object, version); return (IWineD3D *)object; } @@ -120,7 +121,7 @@ static void CDECL wined3d_do_nothing(void) { } -static BOOL wined3d_init(HINSTANCE hInstDLL) +static BOOL wined3d_dll_init(HINSTANCE hInstDLL) { DWORD wined3d_context_tls_idx; HMODULE mod; @@ -236,11 +237,6 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) TRACE("Using the backbuffer for offscreen rendering\n"); wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; } - else if (!strcmp(buffer,"pbuffer")) - { - TRACE("Using PBuffers for offscreen rendering\n"); - wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER; - } else if (!strcmp(buffer,"fbo")) { TRACE("Using FBOs for offscreen rendering\n"); @@ -324,6 +320,12 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) wined3d_settings.allow_multisampling = TRUE; } } + if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size) + && !strcmp(buffer,"enabled")) + { + TRACE("Enforcing strict draw ordering.\n"); + wined3d_settings.strict_draw_ordering = TRUE; + } } if (wined3d_settings.vs_mode == VS_HW) TRACE("Allow HW vertex shaders\n"); @@ -338,7 +340,7 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) return TRUE; } -static BOOL wined3d_destroy(HINSTANCE hInstDLL) +static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL) { DWORD wined3d_context_tls_idx = context_get_tls_idx(); unsigned int i; @@ -478,10 +480,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) switch (fdwReason) { case DLL_PROCESS_ATTACH: - return wined3d_init(hInstDLL); + return wined3d_dll_init(hInstDLL); case DLL_PROCESS_DETACH: - return wined3d_destroy(hInstDLL); + return wined3d_dll_destroy(hInstDLL); case DLL_THREAD_DETACH: { diff --git a/reactos/dll/directx/wine/wined3d/wined3d_private.h b/reactos/dll/directx/wine/wined3d/wined3d_private.h index 1d5cd974645..5c96d764389 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private.h @@ -50,6 +50,7 @@ #define WINED3D_QUIRK_GLSL_CLIP_VARYING 0x00000004 #define WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA 0x00000008 #define WINED3D_QUIRK_NV_CLIP_BROKEN 0x00000010 +#define WINED3D_QUIRK_FBO_TEX_UPDATE 0x00000020 /* Texture format fixups */ @@ -67,10 +68,11 @@ enum fixup_channel_source enum complex_fixup { - COMPLEX_FIXUP_YUY2 = 0, - COMPLEX_FIXUP_UYVY = 1, - COMPLEX_FIXUP_YV12 = 2, - COMPLEX_FIXUP_P8 = 3, + COMPLEX_FIXUP_NONE = 0, + COMPLEX_FIXUP_YUY2 = 1, + COMPLEX_FIXUP_UYVY = 2, + COMPLEX_FIXUP_YV12 = 3, + COMPLEX_FIXUP_P8 = 4, }; #include @@ -234,8 +236,7 @@ static inline float float_24_to_32(DWORD in) #define VBO_HW 1 #define ORM_BACKBUFFER 0 -#define ORM_PBUFFER 1 -#define ORM_FBO 2 +#define ORM_FBO 1 #define SHADER_ARB 1 #define SHADER_GLSL 2 @@ -267,6 +268,7 @@ typedef struct wined3d_settings_s { unsigned int emulated_textureram; char *logo; int allow_multisampling; + BOOL strict_draw_ordering; } wined3d_settings_t; extern wined3d_settings_t wined3d_settings DECLSPEC_HIDDEN; @@ -539,7 +541,8 @@ typedef struct shader_reg_maps WORD usestexldl : 1; WORD usesifc : 1; WORD usescall : 1; - WORD padding : 4; + WORD usesrcp : 1; + WORD padding : 3; /* Whether or not loops are used in this shader, and nesting depth */ unsigned loop_depth; @@ -643,14 +646,6 @@ struct shader_caps { float PixelShader1xMaxValue; DWORD MaxPixelShaderConst; - WINED3DVSHADERCAPS2_0 VS20Caps; - WINED3DPSHADERCAPS2_0 PS20Caps; - - DWORD MaxVShaderInstructionsExecuted; - DWORD MaxPShaderInstructionsExecuted; - DWORD MaxVertexShader30InstructionSlots; - DWORD MaxPixelShader30InstructionSlots; - BOOL VSClipping; }; @@ -693,6 +688,7 @@ struct ps_compile_args { /* Bitmap for NP2 texcoord fixups (16 samplers max currently). D3D9 has a limit of 16 samplers and the fixup is superfluous in D3D10 (unconditional NP2 support mandatory). */ + WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */ }; enum fog_src_type { @@ -711,7 +707,7 @@ struct wined3d_context; typedef struct { void (*shader_handle_instruction)(const struct wined3d_shader_instruction *); void (*shader_select)(const struct wined3d_context *context, BOOL usePS, BOOL useVS); - void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type); + void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size); void (*shader_deselect_depth_blt)(IWineD3DDevice *iface); void (*shader_update_float_vertex_constants)(IWineD3DDevice *iface, UINT start, UINT count); void (*shader_update_float_pixel_constants)(IWineD3DDevice *iface, UINT start, UINT count); @@ -752,7 +748,7 @@ extern int num_lock DECLSPEC_HIDDEN; /* GL related defines */ /* ------------------ */ -#define GL_EXTCALL(FuncName) (GLINFO_LOCATION.FuncName) +#define GL_EXTCALL(f) (gl_info->f) #define D3DCOLOR_B_R(dw) (((dw) >> 16) & 0xFF) #define D3DCOLOR_B_G(dw) (((dw) >> 8) & 0xFF) @@ -771,9 +767,6 @@ extern int num_lock DECLSPEC_HIDDEN; (vec)[3] = D3DCOLOR_A(dw); \ } while(0) -/* DirectX Device Limits */ -/* --------------------- */ -#define MAX_MIP_LEVELS 32 /* Maximum number of mipmap levels. */ #define HIGHEST_TRANSFORMSTATE WINED3DTS_WORLDMATRIX(255) /* Highest value in WINED3DTRANSFORMSTATETYPE */ /* Checking of API calls */ @@ -788,7 +781,7 @@ do { \ TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ \ } else do { \ - FIXME(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n", \ + ERR(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n", \ debug_glerror(err), err, A, __FILE__, __LINE__); \ err = glGetError(); \ } while (err != GL_NO_ERROR); \ @@ -830,13 +823,6 @@ extern const float identity[16] DECLSPEC_HIDDEN; * Compilable extra diagnostics */ -/* Trace information per-vertex: (extremely high amount of trace) */ -#if 0 /* NOTE: Must be 0 in cvs */ -# define VTRACE(A) TRACE A -#else -# define VTRACE(A) -#endif - /* TODO: Confirm each of these works when wined3d move completed */ #if 0 /* NOTE: Must be 0 in cvs */ /* To avoid having to get gigabytes of trace, the following can be compiled in, and at the start @@ -910,7 +896,7 @@ enum wined3d_ffp_emit_idx struct wined3d_stream_info_element { - const struct GlPixelFormatDesc *format_desc; + const struct wined3d_format_desc *format_desc; GLsizei stride; const BYTE *data; UINT stream_idx; @@ -1039,6 +1025,12 @@ enum wined3d_event_query_result WINED3D_EVENT_QUERY_ERROR }; +void wined3d_event_query_destroy(struct wined3d_event_query *query) DECLSPEC_HIDDEN; +enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +HRESULT wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; + struct wined3d_context { const struct wined3d_gl_info *gl_info; @@ -1052,8 +1044,8 @@ struct wined3d_context DWORD numDirtyEntries; DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */ - IWineD3DSurface *surface; - IWineD3DSurface *current_rt; + IWineD3DSwapChainImpl *swapchain; + IWineD3DSurfaceImpl *current_rt; DWORD tid; /* Thread ID which owns this context at the moment */ /* Stores some information about the context state for optimization */ @@ -1089,7 +1081,7 @@ struct wined3d_context HGLRC glCtx; HWND win_handle; HDC hdc; - HPBUFFERARB pbuffer; + int pixel_format; GLint aux_buffers; /* FBOs */ @@ -1097,10 +1089,11 @@ struct wined3d_context struct list fbo_list; struct list fbo_destroy_list; struct fbo_entry *current_fbo; - GLuint src_fbo; GLuint dst_fbo; GLuint fbo_read_binding; GLuint fbo_draw_binding; + BOOL rebind_fbo; + IWineD3DSurfaceImpl **blit_targets; /* Queries */ GLuint *free_occlusion_queries; @@ -1167,60 +1160,69 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_ const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex, const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN; +enum blit_operation +{ + BLIT_OP_BLIT, + BLIT_OP_COLOR_FILL +}; + /* Shaders for color conversions in blits */ struct blit_shader { HRESULT (*alloc_private)(IWineD3DDevice *iface); void (*free_private)(IWineD3DDevice *iface); - HRESULT (*set_shader)(IWineD3DDevice *iface, const struct GlPixelFormatDesc *format_desc, - GLenum textype, UINT width, UINT height); + HRESULT (*set_shader)(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface); void (*unset_shader)(IWineD3DDevice *iface); - BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); + BOOL (*blit_supported)(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, const struct wined3d_format_desc *src_format_desc, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, const struct wined3d_format_desc *dst_format_desc); + HRESULT (*color_fill)(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color); }; extern const struct blit_shader ffp_blit DECLSPEC_HIDDEN; extern const struct blit_shader arbfp_blit DECLSPEC_HIDDEN; +extern const struct blit_shader cpu_blit DECLSPEC_HIDDEN; -typedef enum ContextUsage { - CTXUSAGE_RESOURCELOAD = 1, /* Only loads textures: No State is applied */ - CTXUSAGE_DRAWPRIM = 2, /* OpenGL states are set up for blitting DirectDraw surfaces */ - CTXUSAGE_BLIT = 3, /* OpenGL states are set up 3D drawing */ - CTXUSAGE_CLEAR = 4, /* Drawable and states are set up for clearing */ -} ContextUsage; +/* Temporary blit_shader helper functions */ +HRESULT arbfp_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, + IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op, + DWORD Filter) DECLSPEC_HIDDEN; -struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, - IWineD3DSurface *target, enum ContextUsage usage) DECLSPEC_HIDDEN; +struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target) DECLSPEC_HIDDEN; void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query) DECLSPEC_HIDDEN; void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; -void context_resource_released(IWineD3DDevice *iface, - IWineD3DResource *resource, WINED3DRESOURCETYPE type) DECLSPEC_HIDDEN; -void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo) DECLSPEC_HIDDEN; +void context_apply_blit_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device, + IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN; +void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, + IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN; void context_attach_depth_stencil_fbo(struct wined3d_context *context, - GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) DECLSPEC_HIDDEN; -void context_attach_surface_fbo(const struct wined3d_context *context, - GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) DECLSPEC_HIDDEN; -struct wined3d_context *context_create(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, - BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *present_parameters) DECLSPEC_HIDDEN; + GLenum fbo_target, IWineD3DSurfaceImpl *depth_stencil, BOOL use_render_buffer) DECLSPEC_HIDDEN; +void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo) DECLSPEC_HIDDEN; +struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target, + const struct wined3d_format_desc *ds_format_desc) DECLSPEC_HIDDEN; void context_destroy(IWineD3DDeviceImpl *This, struct wined3d_context *context) DECLSPEC_HIDDEN; void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN; void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN; +void context_resource_released(IWineD3DDevice *iface, + IWineD3DResource *resource, WINED3DRESOURCETYPE type) 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; - -void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain) DECLSPEC_HIDDEN; -HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain) DECLSPEC_HIDDEN; +void context_surface_update(struct wined3d_context *context, IWineD3DSurfaceImpl *surface) DECLSPEC_HIDDEN; /* Macros for doing basic GPU detection based on opengl capabilities */ #define WINE_D3D6_CAPABLE(gl_info) (gl_info->supported[ARB_MULTITEXTURE]) #define WINE_D3D7_CAPABLE(gl_info) (gl_info->supported[ARB_TEXTURE_COMPRESSION] && gl_info->supported[ARB_TEXTURE_CUBE_MAP] && gl_info->supported[ARB_TEXTURE_ENV_DOT3]) #define WINE_D3D8_CAPABLE(gl_info) WINE_D3D7_CAPABLE(gl_info) && (gl_info->supported[ARB_MULTISAMPLE] && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP]) #define WINE_D3D9_CAPABLE(gl_info) WINE_D3D8_CAPABLE(gl_info) && (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[ARB_VERTEX_SHADER]) +#define WINE_D3D10_CAPABLE(gl_info) WINE_D3D9_CAPABLE(gl_info) && (gl_info->supported[EXT_GPU_SHADER4]) /***************************************************************************** * Internal representation of a light @@ -1251,7 +1253,6 @@ typedef struct WineD3D_PixelFormat int redSize, greenSize, blueSize, alphaSize, colorSize; int depthSize, stencilSize; BOOL windowDrawable; - BOOL pbufferDrawable; BOOL doubleBuffer; int auxBuffers; int numSamples; @@ -1259,9 +1260,9 @@ typedef struct WineD3D_PixelFormat enum wined3d_gl_vendor { - GL_VENDOR_WINE, + GL_VENDOR_UNKNOWN, GL_VENDOR_APPLE, - GL_VENDOR_ATI, + GL_VENDOR_FGLRX, GL_VENDOR_INTEL, GL_VENDOR_MESA, GL_VENDOR_NVIDIA, @@ -1270,7 +1271,7 @@ enum wined3d_gl_vendor enum wined3d_pci_vendor { - HW_VENDOR_WINE = 0x0000, + HW_VENDOR_SOFTWARE = 0x0000, HW_VENDOR_ATI = 0x1002, HW_VENDOR_NVIDIA = 0x10de, HW_VENDOR_INTEL = 0x8086, @@ -1287,7 +1288,7 @@ enum wined3d_pci_device CARD_ATI_RADEON_XPRESS_200M = 0x5955, CARD_ATI_RADEON_X700 = 0x5e4c, CARD_ATI_RADEON_X1600 = 0x71c2, - CARD_ATI_RADEON_HD2300 = 0x7210, + CARD_ATI_RADEON_HD2350 = 0x94c7, CARD_ATI_RADEON_HD2600 = 0x9581, CARD_ATI_RADEON_HD2900 = 0x9400, CARD_ATI_RADEON_HD3200 = 0x9620, @@ -1418,6 +1419,7 @@ struct wined3d_gl_limits struct wined3d_gl_info { + DWORD glsl_version; UINT vidmem; struct wined3d_gl_limits limits; DWORD reserved_glsl_constants; @@ -1433,7 +1435,7 @@ struct wined3d_gl_info WGL_EXT_FUNCS_GEN #undef USE_GL_FUNC - struct GlPixelFormatDesc *gl_formats; + struct wined3d_format_desc *gl_formats; }; struct wined3d_driver_info @@ -1469,7 +1471,7 @@ struct wined3d_adapter BOOL initPixelFormats(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor) DECLSPEC_HIDDEN; BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; -extern long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram) DECLSPEC_HIDDEN; +extern unsigned int WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, unsigned int glram) DECLSPEC_HIDDEN; extern void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; /***************************************************************************** @@ -1564,14 +1566,9 @@ typedef struct IWineD3DImpl struct wined3d_adapter adapters[1]; } IWineD3DImpl; -extern const IWineD3DVtbl IWineD3D_Vtbl DECLSPEC_HIDDEN; - +HRESULT wined3d_init(IWineD3DImpl *wined3d, UINT version, IUnknown *parent) DECLSPEC_HIDDEN; BOOL wined3d_register_window(HWND window, struct IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN; -BOOL InitAdapters(IWineD3DImpl *This) DECLSPEC_HIDDEN; - -/* A helper function that dumps a resource list */ -void dumpResources(struct list *list) DECLSPEC_HIDDEN; /***************************************************************************** * IWineD3DDevice implementation structure @@ -1656,9 +1653,10 @@ struct IWineD3DDeviceImpl unsigned int highest_dirty_ps_const, highest_dirty_vs_const; /* Render Target Support */ - IWineD3DSurface **render_targets; - IWineD3DSurface *auto_depth_stencil_buffer; - IWineD3DSurface *stencilBufferTarget; + IWineD3DSurfaceImpl **render_targets; + IWineD3DSurfaceImpl *auto_depth_stencil; + IWineD3DSurfaceImpl *onscreen_depth_stencil; + IWineD3DSurfaceImpl *depth_stencil; /* palettes texture management */ UINT NumberOfPalettes; @@ -1701,12 +1699,12 @@ struct IWineD3DDeviceImpl /* Stream source management */ struct wined3d_stream_info strided_streams; const WineDirect3DVertexStridedData *up_strided; + struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; + unsigned int num_buffer_queries; /* Context management */ struct wined3d_context **contexts; UINT numContexts; - struct wined3d_context *pbufferContext; /* The context that has a pbuffer as drawable */ - DWORD pbufferWidth, pbufferHeight; /* Size of the buffer drawable */ /* High level patch management */ #define PATCHMAP_SIZE 43 @@ -1715,6 +1713,9 @@ struct IWineD3DDeviceImpl struct WineD3DRectPatch *currentPatch; }; +BOOL device_context_add(IWineD3DDeviceImpl *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void device_context_remove(IWineD3DDeviceImpl *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect) DECLSPEC_HIDDEN; HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d, UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent, IWineD3DDeviceParent *device_parent) DECLSPEC_HIDDEN; @@ -1725,6 +1726,8 @@ void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource) D void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource) DECLSPEC_HIDDEN; void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, BOOL use_vshader, struct wined3d_stream_info *stream_info, BOOL *fixup) DECLSPEC_HIDDEN; +void device_switch_onscreen_ds(IWineD3DDeviceImpl *device, struct wined3d_context *context, + IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN; void device_update_stream_info(IWineD3DDeviceImpl *device, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) DECLSPEC_HIDDEN; @@ -1770,7 +1773,7 @@ typedef struct IWineD3DResourceClass WINED3DPOOL pool; UINT size; DWORD usage; - const struct GlPixelFormatDesc *format_desc; + const struct wined3d_format_desc *format_desc; DWORD priority; BYTE *allocatedMemory; /* Pointer to the real data location */ BYTE *heapMemory; /* Pointer to the HeapAlloced block of memory */ @@ -1793,7 +1796,7 @@ DWORD resource_get_priority(IWineD3DResource *iface) DECLSPEC_HIDDEN; HRESULT resource_get_private_data(IWineD3DResource *iface, REFGUID guid, void *data, DWORD *data_size) DECLSPEC_HIDDEN; HRESULT resource_init(IWineD3DResource *iface, WINED3DRESOURCETYPE resource_type, - IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, + IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; WINED3DRESOURCETYPE resource_get_type(IWineD3DResource *iface) DECLSPEC_HIDDEN; DWORD resource_set_priority(IWineD3DResource *iface, DWORD new_priority) DECLSPEC_HIDDEN; @@ -1801,7 +1804,7 @@ HRESULT resource_set_private_data(IWineD3DResource *iface, REFGUID guid, const void *data, DWORD data_size, DWORD flags) DECLSPEC_HIDDEN; /* Tests show that the start address of resources is 32 byte aligned */ -#define RESOURCE_ALIGNMENT 32 +#define RESOURCE_ALIGNMENT 16 /***************************************************************************** * IWineD3DBaseTexture D3D- > openGL state map lookups @@ -1818,10 +1821,8 @@ typedef enum winetexturestates { WINED3DTEXSTA_MAXMIPLEVEL = 7, WINED3DTEXSTA_MAXANISOTROPY = 8, WINED3DTEXSTA_SRGBTEXTURE = 9, - WINED3DTEXSTA_ELEMENTINDEX = 10, - WINED3DTEXSTA_DMAPOFFSET = 11, - WINED3DTEXSTA_TSSADDRESSW = 12, - MAX_WINETEXTURESTATES = 13, + WINED3DTEXSTA_SHADOW = 10, + MAX_WINETEXTURESTATES = 11, } winetexturestates; enum WINED3DSRGB @@ -1845,7 +1846,9 @@ struct gl_texture typedef struct IWineD3DBaseTextureClass { struct gl_texture texture_rgb, texture_srgb; - UINT levels; + IWineD3DResourceImpl **sub_resources; + UINT layer_count; + UINT level_count; float pow2Matrix[16]; UINT LOD; WINED3DTEXTUREFILTERTYPE filterType; @@ -1858,10 +1861,11 @@ typedef struct IWineD3DBaseTextureClass void (*internal_preload)(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); } IWineD3DBaseTextureClass; -void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) DECLSPEC_HIDDEN; -BOOL surface_init_sysmem(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -BOOL surface_is_offscreen(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -void surface_prepare_texture(IWineD3DSurfaceImpl *surface, BOOL srgb) DECLSPEC_HIDDEN; +void surface_internal_preload(IWineD3DSurfaceImpl *surface, enum WINED3DSRGB srgb) DECLSPEC_HIDDEN; +BOOL surface_init_sysmem(IWineD3DSurfaceImpl *surface) DECLSPEC_HIDDEN; +BOOL surface_is_offscreen(IWineD3DSurfaceImpl *iface) DECLSPEC_HIDDEN; +void surface_prepare_texture(IWineD3DSurfaceImpl *surface, + const struct wined3d_gl_info *gl_info, BOOL srgb) DECLSPEC_HIDDEN; typedef struct IWineD3DBaseTextureImpl { @@ -1883,9 +1887,12 @@ WINED3DTEXTUREFILTERTYPE basetexture_get_autogen_filter_type(IWineD3DBaseTexture BOOL basetexture_get_dirty(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN; DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN; DWORD basetexture_get_lod(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN; -HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type, - IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, - WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; +IWineD3DResourceImpl *basetexture_get_sub_resource(IWineD3DBaseTextureImpl *texture, + UINT layer, UINT level) DECLSPEC_HIDDEN; +HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT layer_count, UINT level_count, + WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage, + const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent, + const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE filter_type) DECLSPEC_HIDDEN; BOOL basetexture_set_dirty(IWineD3DBaseTexture *iface, BOOL dirty) DECLSPEC_HIDDEN; @@ -1903,7 +1910,6 @@ typedef struct IWineD3DTextureImpl IWineD3DBaseTextureClass baseTexture; /* IWineD3DTexture */ - IWineD3DSurface *surfaces[MAX_MIP_LEVELS]; UINT target; BOOL cond_np2; @@ -1922,9 +1928,6 @@ typedef struct IWineD3DCubeTextureImpl const IWineD3DCubeTextureVtbl *lpVtbl; IWineD3DResourceClass resource; IWineD3DBaseTextureClass baseTexture; - - /* IWineD3DCubeTexture */ - IWineD3DSurface *surfaces[6][MAX_MIP_LEVELS]; } IWineD3DCubeTextureImpl; HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels, @@ -1971,9 +1974,6 @@ typedef struct IWineD3DVolumeTextureImpl const IWineD3DVolumeTextureVtbl *lpVtbl; IWineD3DResourceClass resource; IWineD3DBaseTextureClass baseTexture; - - /* IWineD3DVolumeTexture */ - IWineD3DVolume *volumes[MAX_MIP_LEVELS]; } IWineD3DVolumeTextureImpl; HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height, @@ -2009,8 +2009,8 @@ typedef struct { struct fbo_entry { struct list entry; - IWineD3DSurface **render_targets; - IWineD3DSurface *depth_stencil; + IWineD3DSurfaceImpl **render_targets; + IWineD3DSurfaceImpl *depth_stencil; BOOL attached; GLuint id; }; @@ -2052,9 +2052,6 @@ struct IWineD3DSurfaceImpl /* A method to retrieve the drawable size. Not in the Vtable to make it changeable */ void (*get_drawable_size)(struct wined3d_context *context, UINT *width, UINT *height); - /* Oversized texture */ - RECT glRect; - /* PBO */ GLuint pbo; GLuint texture_name; @@ -2082,6 +2079,7 @@ struct IWineD3DSurfaceImpl struct list renderbuffers; renderbuffer_entry_t *current_renderbuffer; + SIZE ds_current_size; /* DirectDraw clippers */ IWineD3DClipper *clipper; @@ -2097,13 +2095,14 @@ struct IWineD3DSurfaceImpl extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl DECLSPEC_HIDDEN; extern const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl DECLSPEC_HIDDEN; -UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, +UINT surface_calculate_size(const struct wined3d_format_desc *format_desc, UINT alignment, UINT width, UINT height) DECLSPEC_HIDDEN; void surface_gdi_cleanup(IWineD3DSurfaceImpl *This) DECLSPEC_HIDDEN; HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; +void surface_translate_frontbuffer_coords(IWineD3DSurfaceImpl *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN; /* Predeclare the shared Surface functions */ HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, @@ -2153,13 +2152,13 @@ const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface) DECLS void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; -void get_drawable_size_pbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; +void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, + const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter) DECLSPEC_HIDDEN; void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) DECLSPEC_HIDDEN; /* Surface flags: */ -#define SFLAG_OVERSIZE 0x00000001 /* Surface is bigger than gl size, blts only */ #define SFLAG_CONVERTED 0x00000002 /* Converted for color keying or Palettized */ #define SFLAG_DIBSECTION 0x00000004 /* Has a DIB section attached for GetDC */ #define SFLAG_LOCKABLE 0x00000008 /* Surface can be locked */ @@ -2186,7 +2185,6 @@ void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) DECLSPE #define SFLAG_SWAPCHAIN 0x01000000 /* The surface is part of a swapchain */ /* In some conditions the surface memory must not be freed: - * SFLAG_OVERSIZE: Not all data can be kept in GL * SFLAG_CONVERTED: Converting the data back would take too long * SFLAG_DIBSECTION: The dib code manages the memory * SFLAG_LOCKED: The app requires access to the surface data @@ -2194,8 +2192,7 @@ void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) DECLSPE * SFLAG_PBO: PBOs don't use 'normal' memory. It is either allocated by the driver or must be NULL. * SFLAG_CLIENT: OpenGL uses our memory as backup */ -#define SFLAG_DONOTFREE (SFLAG_OVERSIZE | \ - SFLAG_CONVERTED | \ +#define SFLAG_DONOTFREE (SFLAG_CONVERTED | \ SFLAG_DIBSECTION | \ SFLAG_LOCKED | \ SFLAG_DYNLOCK | \ @@ -2212,38 +2209,19 @@ void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) DECLSPE SFLAG_DS_OFFSCREEN) #define SFLAG_DS_DISCARDED SFLAG_DS_LOCATIONS -BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]) DECLSPEC_HIDDEN; - typedef enum { NO_CONVERSION, CONVERT_PALETTED, CONVERT_PALETTED_CK, CONVERT_CK_565, CONVERT_CK_5551, - CONVERT_CK_4444, - CONVERT_CK_4444_ARGB, - CONVERT_CK_1555, - CONVERT_555, CONVERT_CK_RGB24, - CONVERT_CK_8888, - CONVERT_CK_8888_ARGB, - CONVERT_RGB32_888, - CONVERT_V8U8, - CONVERT_L6V5U5, - CONVERT_X8L8V8U8, - CONVERT_Q8W8V8U8, - CONVERT_V16U16, - CONVERT_A4L4, - CONVERT_G16R16, - CONVERT_R16G16F, - CONVERT_R32G32F, - CONVERT_D15S1, - CONVERT_D24X4S4, - CONVERT_D24FS8, + CONVERT_RGB32_888 } CONVERT_TYPES; -HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, - GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode) DECLSPEC_HIDDEN; +HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, + struct wined3d_format_desc *desc, CONVERT_TYPES *convert) DECLSPEC_HIDDEN; +void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) DECLSPEC_HIDDEN; BOOL palette9_changed(IWineD3DSurfaceImpl *This) DECLSPEC_HIDDEN; @@ -2253,7 +2231,7 @@ BOOL palette9_changed(IWineD3DSurfaceImpl *This) DECLSPEC_HIDDEN; struct wined3d_vertex_declaration_element { - const struct GlPixelFormatDesc *format_desc; + const struct wined3d_format_desc *format_desc; BOOL ffp_valid; WORD input_slot; WORD offset; @@ -2432,6 +2410,14 @@ HRESULT stateblock_init(IWineD3DStateBlockImpl *stateblock, IWineD3DDeviceImpl *device, WINED3DSTATEBLOCKTYPE type) DECLSPEC_HIDDEN; void stateblock_init_contained_states(IWineD3DStateBlockImpl *object) DECLSPEC_HIDDEN; +static inline void stateblock_apply_state(DWORD state, IWineD3DStateBlockImpl *stateblock, + struct wined3d_context *context) +{ + const struct StateEntry *statetable = stateblock->device->StateTable; + DWORD rep = statetable[state].representative; + statetable[rep].apply(rep, stateblock, context); +} + /* Direct3D terminology with little modifications. We do not have an issued state * because only the driver knows about it, but we have a created state because d3d * allows GetData on a created issue, but opengl doesn't @@ -2485,6 +2471,9 @@ struct wined3d_map_range #define WINED3D_BUFFER_CREATEBO 0x04 /* Attempt to create a buffer object next PreLoad */ #define WINED3D_BUFFER_DOUBLEBUFFER 0x08 /* Use a vbo and local allocated memory */ #define WINED3D_BUFFER_FLUSH 0x10 /* Manual unmap flushing */ +#define WINED3D_BUFFER_DISCARD 0x20 /* A DISCARD lock has occurred since the last PreLoad */ +#define WINED3D_BUFFER_NOSYNC 0x40 /* All locks since the last PreLoad had NOOVERWRITE set */ +#define WINED3D_BUFFER_APPLESYNC 0x80 /* Using sync as in GL_APPLE_flush_buffer_range */ struct wined3d_buffer { @@ -2503,6 +2492,7 @@ struct wined3d_buffer LONG lock_count; struct wined3d_map_range *maps; ULONG maps_size, modified_areas; + struct wined3d_event_query *query; /* conversion stuff */ UINT decl_change_count, full_conversion_count; @@ -2514,8 +2504,9 @@ struct wined3d_buffer UINT *conversion_shift; /* NULL if no shifted conversion */ }; -const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer_object) DECLSPEC_HIDDEN; -BYTE *buffer_get_sysmem(struct wined3d_buffer *This) DECLSPEC_HIDDEN; +const BYTE *buffer_get_memory(IWineD3DBuffer *iface, const struct wined3d_gl_info *gl_info, + GLuint *buffer_object) DECLSPEC_HIDDEN; +BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; HRESULT buffer_init(struct wined3d_buffer *buffer, IWineD3DDeviceImpl *device, UINT size, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, GLenum bind_hint, const char *data, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; @@ -2530,7 +2521,8 @@ struct wined3d_rendertarget_view IUnknown *parent; }; -extern const IWineD3DRendertargetViewVtbl wined3d_rendertarget_view_vtbl DECLSPEC_HIDDEN; +void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view, + IWineD3DResource *resource, IUnknown *parent) DECLSPEC_HIDDEN; /***************************************************************************** * IWineD3DSwapChainImpl implementation structure (extends IUnknown) @@ -2546,21 +2538,23 @@ struct IWineD3DSwapChainImpl IWineD3DDeviceImpl *device; /* IWineD3DSwapChain fields */ - IWineD3DSurface **backBuffer; - IWineD3DSurface *frontBuffer; + IWineD3DSurfaceImpl **back_buffers; + IWineD3DSurfaceImpl *front_buffer; WINED3DPRESENT_PARAMETERS presentParms; DWORD orig_width, orig_height; WINED3DFORMAT orig_fmt; WINED3DGAMMARAMP orig_gamma; BOOL render_to_fbo; + const struct wined3d_format_desc *ds_format; - long prev_time, frames; /* Performance tracking */ + LONG prev_time, frames; /* Performance tracking */ unsigned int vSyncCounter; struct wined3d_context **context; unsigned int num_contexts; HWND win_handle; + HWND device_window; }; const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl DECLSPEC_HIDDEN; @@ -2580,7 +2574,7 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *ifac HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE *pMode) DECLSPEC_HIDDEN; HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, - IWineD3DDevice **ppDevice) DECLSPEC_HIDDEN; + IWineD3DDevice **device) DECLSPEC_HIDDEN; HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) DECLSPEC_HIDDEN; HRESULT WINAPI IWineD3DBaseSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, @@ -2624,6 +2618,9 @@ const char *debug_d3dtop(WINED3DTEXTUREOP d3dtop) DECLSPEC_HIDDEN; void dump_color_fixup_desc(struct color_fixup_desc fixup) DECLSPEC_HIDDEN; const char *debug_surflocation(DWORD flag) DECLSPEC_HIDDEN; +/* Color conversion routines */ +DWORD color_convert_argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) DECLSPEC_HIDDEN; + /* Routines for GL <-> D3D values */ GLenum StencilOp(DWORD op) DECLSPEC_HIDDEN; GLenum CompareFunc(DWORD func) DECLSPEC_HIDDEN; @@ -2650,18 +2647,19 @@ void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) DECLSPEC_HIDDEN; -void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect) DECLSPEC_HIDDEN; -GLenum surface_get_gl_buffer(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; -void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) DECLSPEC_HIDDEN; -void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, +void surface_add_dirty_rect(IWineD3DSurfaceImpl *surface, const RECT *dirty_rect) DECLSPEC_HIDDEN; +GLenum surface_get_gl_buffer(IWineD3DSurfaceImpl *surface) DECLSPEC_HIDDEN; +void surface_load_ds_location(IWineD3DSurfaceImpl *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; +void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; +void surface_set_compatible_renderbuffer(IWineD3DSurfaceImpl *surface, unsigned int width, unsigned int height) DECLSPEC_HIDDEN; -void surface_set_texture_name(IWineD3DSurface *iface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN; -void surface_set_texture_target(IWineD3DSurface *iface, GLenum target) DECLSPEC_HIDDEN; +void surface_set_texture_name(IWineD3DSurfaceImpl *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN; +void surface_set_texture_target(IWineD3DSurfaceImpl *surface, GLenum target) DECLSPEC_HIDDEN; -BOOL getColorBits(const struct GlPixelFormatDesc *format_desc, +BOOL getColorBits(const struct wined3d_format_desc *format_desc, short *redSize, short *greenSize, short *blueSize, short *alphaSize, short *totalSize) DECLSPEC_HIDDEN; -BOOL getDepthStencilBits(const struct GlPixelFormatDesc *format_desc, +BOOL getDepthStencilBits(const struct wined3d_format_desc *format_desc, short *depthSize, short *stencilSize) DECLSPEC_HIDDEN; /* Math utils */ @@ -2941,8 +2939,8 @@ struct IWineD3DPaletteImpl { DWORD Flags; }; -extern const IWineD3DPaletteVtbl IWineD3DPalette_Vtbl DECLSPEC_HIDDEN; -DWORD IWineD3DPaletteImpl_Size(DWORD dwFlags) DECLSPEC_HIDDEN; +HRESULT wined3d_palette_init(IWineD3DPaletteImpl *palette, IWineD3DDeviceImpl *device, + DWORD flags, const PALETTEENTRY *entries, IUnknown *parent) DECLSPEC_HIDDEN; /* DirectDraw utility functions */ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN; @@ -2952,17 +2950,23 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN; */ /* WineD3D pixel format flags */ -#define WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING 0x1 -#define WINED3DFMT_FLAG_FILTERING 0x2 -#define WINED3DFMT_FLAG_DEPTH 0x4 -#define WINED3DFMT_FLAG_STENCIL 0x8 -#define WINED3DFMT_FLAG_RENDERTARGET 0x10 -#define WINED3DFMT_FLAG_FOURCC 0x20 -#define WINED3DFMT_FLAG_FBO_ATTACHABLE 0x40 -#define WINED3DFMT_FLAG_COMPRESSED 0x80 -#define WINED3DFMT_FLAG_GETDC 0x100 - -struct GlPixelFormatDesc +#define WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING 0x00000001 +#define WINED3DFMT_FLAG_FILTERING 0x00000002 +#define WINED3DFMT_FLAG_DEPTH 0x00000004 +#define WINED3DFMT_FLAG_STENCIL 0x00000008 +#define WINED3DFMT_FLAG_RENDERTARGET 0x00000010 +#define WINED3DFMT_FLAG_FOURCC 0x00000020 +#define WINED3DFMT_FLAG_FBO_ATTACHABLE 0x00000040 +#define WINED3DFMT_FLAG_COMPRESSED 0x00000080 +#define WINED3DFMT_FLAG_GETDC 0x00000100 +#define WINED3DFMT_FLAG_FLOAT 0x00000200 +#define WINED3DFMT_FLAG_BUMPMAP 0x00000400 +#define WINED3DFMT_FLAG_SRGB_READ 0x00000800 +#define WINED3DFMT_FLAG_SRGB_WRITE 0x00001000 +#define WINED3DFMT_FLAG_VTF 0x00002000 +#define WINED3DFMT_FLAG_SHADOW 0x00004000 + +struct wined3d_format_desc { WINED3DFORMAT format; DWORD red_mask; @@ -2989,12 +2993,14 @@ struct GlPixelFormatDesc GLint rtInternal; GLint glFormat; GLint glType; + UINT conv_byte_count; unsigned int Flags; float heightscale; struct color_fixup_desc color_fixup; + void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height); }; -const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, +const struct wined3d_format_desc *getFormatDescEntry(WINED3DFORMAT fmt, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; static inline BOOL use_vs(IWineD3DStateBlockImpl *stateblock) @@ -3013,9 +3019,9 @@ static inline BOOL use_ps(IWineD3DStateBlockImpl *stateblock) return (stateblock->pixelShader && stateblock->device->ps_selected_mode != SHADER_NONE); } -void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, - WINED3DRECT *src_rect, IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, - const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) DECLSPEC_HIDDEN; +void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, + const RECT *src_rect, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, + const WINED3DTEXTUREFILTERTYPE filter) DECLSPEC_HIDDEN; /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL" @@ -3024,4 +3030,6 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) +#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffff) << 16) | (min & 0xffff)) + #endif diff --git a/reactos/include/reactos/wine/wined3d.idl b/reactos/include/reactos/wine/wined3d.idl index 6364f9cfe89..1da7d44b738 100644 --- a/reactos/include/reactos/wine/wined3d.idl +++ b/reactos/include/reactos/wine/wined3d.idl @@ -275,9 +275,7 @@ typedef enum _WINED3DFORMAT typedef enum _WINED3DRENDERSTATETYPE { - WINED3DRS_TEXTUREHANDLE = 1, /* d3d7 */ WINED3DRS_ANTIALIAS = 2, /* d3d7 */ - WINED3DRS_TEXTUREADDRESS = 3, /* d3d7 */ WINED3DRS_TEXTUREPERSPECTIVE = 4, /* d3d7 */ WINED3DRS_WRAPU = 5, /* d3d7 */ WINED3DRS_WRAPV = 6, /* d3d7 */ @@ -291,11 +289,8 @@ typedef enum _WINED3DRENDERSTATETYPE WINED3DRS_ZWRITEENABLE = 14, WINED3DRS_ALPHATESTENABLE = 15, WINED3DRS_LASTPIXEL = 16, - WINED3DRS_TEXTUREMAG = 17, /* d3d7 */ - WINED3DRS_TEXTUREMIN = 18, /* d3d7 */ WINED3DRS_SRCBLEND = 19, WINED3DRS_DESTBLEND = 20, - WINED3DRS_TEXTUREMAPBLEND = 21, /* d3d7 */ WINED3DRS_CULLMODE = 22, WINED3DRS_ZFUNC = 23, WINED3DRS_ALPHAREF = 24, @@ -316,9 +311,6 @@ typedef enum _WINED3DRENDERSTATETYPE WINED3DRS_STIPPLEENABLE = 39, /* d3d7 */ WINED3DRS_EDGEANTIALIAS = 40, /* d3d7, d3d8 */ WINED3DRS_COLORKEYENABLE = 41, /* d3d7 */ - WINED3DRS_BORDERCOLOR = 43, /* d3d7 */ - WINED3DRS_TEXTUREADDRESSU = 44, /* d3d7 */ - WINED3DRS_TEXTUREADDRESSV = 45, /* d3d7 */ WINED3DRS_MIPMAPLODBIAS = 46, /* d3d7 */ WINED3DRS_ZBIAS = 47, /* d3d7, d3d8 */ WINED3DRS_RANGEFOGENABLE = 48, @@ -334,38 +326,6 @@ typedef enum _WINED3DRENDERSTATETYPE WINED3DRS_STENCILMASK = 58, WINED3DRS_STENCILWRITEMASK = 59, WINED3DRS_TEXTUREFACTOR = 60, - WINED3DRS_STIPPLEPATTERN00 = 64, - WINED3DRS_STIPPLEPATTERN01 = 65, - WINED3DRS_STIPPLEPATTERN02 = 66, - WINED3DRS_STIPPLEPATTERN03 = 67, - WINED3DRS_STIPPLEPATTERN04 = 68, - WINED3DRS_STIPPLEPATTERN05 = 69, - WINED3DRS_STIPPLEPATTERN06 = 70, - WINED3DRS_STIPPLEPATTERN07 = 71, - WINED3DRS_STIPPLEPATTERN08 = 72, - WINED3DRS_STIPPLEPATTERN09 = 73, - WINED3DRS_STIPPLEPATTERN10 = 74, - WINED3DRS_STIPPLEPATTERN11 = 75, - WINED3DRS_STIPPLEPATTERN12 = 76, - WINED3DRS_STIPPLEPATTERN13 = 77, - WINED3DRS_STIPPLEPATTERN14 = 78, - WINED3DRS_STIPPLEPATTERN15 = 79, - WINED3DRS_STIPPLEPATTERN16 = 80, - WINED3DRS_STIPPLEPATTERN17 = 81, - WINED3DRS_STIPPLEPATTERN18 = 82, - WINED3DRS_STIPPLEPATTERN19 = 83, - WINED3DRS_STIPPLEPATTERN20 = 84, - WINED3DRS_STIPPLEPATTERN21 = 85, - WINED3DRS_STIPPLEPATTERN22 = 86, - WINED3DRS_STIPPLEPATTERN23 = 87, - WINED3DRS_STIPPLEPATTERN24 = 88, - WINED3DRS_STIPPLEPATTERN25 = 89, - WINED3DRS_STIPPLEPATTERN26 = 90, - WINED3DRS_STIPPLEPATTERN27 = 91, - WINED3DRS_STIPPLEPATTERN28 = 92, - WINED3DRS_STIPPLEPATTERN29 = 93, - WINED3DRS_STIPPLEPATTERN30 = 94, - WINED3DRS_STIPPLEPATTERN31 = 95, WINED3DRS_WRAP0 = 128, WINED3DRS_WRAP1 = 129, WINED3DRS_WRAP2 = 130, @@ -407,8 +367,6 @@ typedef enum _WINED3DRENDERSTATETYPE WINED3DRS_COLORWRITEENABLE = 168, WINED3DRS_TWEENFACTOR = 170, WINED3DRS_BLENDOP = 171, - WINED3DRS_POSITIONORDER = 172, - WINED3DRS_NORMALORDER = 173, WINED3DRS_POSITIONDEGREE = 172, WINED3DRS_NORMALDEGREE = 173, WINED3DRS_SCISSORTESTENABLE = 174, @@ -3452,6 +3410,15 @@ interface IWineD3DDevice : IWineD3DBase [in] D3DCB_ENUMRESOURCES callback, [in] void *data ); + HRESULT GetSurfaceFromDC( + [in] HDC dc, + [out] IWineD3DSurface **surface + ); + HRESULT AcquireFocusWindow( + [in] HWND window + ); + void ReleaseFocusWindow( + ); } IWineD3D *WineDirect3DCreate(UINT dxVersion, IUnknown *parent); -- 2.17.1