From dbd0569bd7112949fce9366356e687e5e8a2ced7 Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Tue, 30 Sep 2008 12:03:48 +0000 Subject: [PATCH] Sync Wined3d to Wine 1.1.5 (great work done by: Kamil Hornicek) svn path=/trunk/; revision=36600 --- reactos/dll/directx/wine/d3d8/d3d8_main.c | 5 + reactos/dll/directx/wine/d3d8/d3d8_private.h | 117 +- reactos/dll/directx/wine/d3d8/device.c | 92 +- reactos/dll/directx/wine/d3d8/directx.c | 6 +- reactos/dll/directx/wine/d3d8/stateblock.c | 2 +- .../dll/directx/wine/d3d8/vertexdeclaration.c | 4 +- reactos/dll/directx/wine/d3d8/volume.c | 2 +- reactos/dll/directx/wine/d3d9/Makefile.in | 5 +- reactos/dll/directx/wine/d3d9/cubetexture.c | 2 +- reactos/dll/directx/wine/d3d9/d3d9.spec | 12 +- reactos/dll/directx/wine/d3d9/d3d9_main.c | 44 +- reactos/dll/directx/wine/d3d9/d3d9_private.h | 269 +- reactos/dll/directx/wine/d3d9/device.c | 520 +- reactos/dll/directx/wine/d3d9/directx.c | 91 +- reactos/dll/directx/wine/d3d9/indexbuffer.c | 2 +- reactos/dll/directx/wine/d3d9/pixelshader.c | 18 +- reactos/dll/directx/wine/d3d9/query.c | 2 +- reactos/dll/directx/wine/d3d9/stateblock.c | 8 +- reactos/dll/directx/wine/d3d9/swapchain.c | 8 +- reactos/dll/directx/wine/d3d9/texture.c | 2 +- reactos/dll/directx/wine/d3d9/vertexbuffer.c | 2 +- .../dll/directx/wine/d3d9/vertexdeclaration.c | 22 +- reactos/dll/directx/wine/d3d9/vertexshader.c | 18 +- reactos/dll/directx/wine/d3d9/volume.c | 2 +- reactos/dll/directx/wine/d3d9/volumetexture.c | 2 +- .../directx/wine/wined3d/arb_program_shader.c | 2507 ++++++++-- .../wine/wined3d/ati_fragment_shader.c | 1121 +++++ reactos/dll/directx/wine/wined3d/baseshader.c | 153 +- .../dll/directx/wine/wined3d/basetexture.c | 137 +- reactos/dll/directx/wine/wined3d/context.c | 1036 +++- .../dll/directx/wine/wined3d/cubetexture.c | 83 +- reactos/dll/directx/wine/wined3d/device.c | 1971 +++++--- reactos/dll/directx/wine/wined3d/directx.c | 3185 ++++++++---- reactos/dll/directx/wine/wined3d/drawprim.c | 549 +-- .../dll/directx/wine/wined3d/glsl_shader.c | 1050 +++- .../dll/directx/wine/wined3d/indexbuffer.c | 29 +- .../wine/wined3d/nvidia_texture_shader.c | 825 ++++ reactos/dll/directx/wine/wined3d/palette.c | 30 +- .../dll/directx/wine/wined3d/pixelshader.c | 201 +- reactos/dll/directx/wine/wined3d/query.c | 339 +- reactos/dll/directx/wine/wined3d/resource.c | 10 +- reactos/dll/directx/wine/wined3d/state.c | 4345 ++++++++++------- reactos/dll/directx/wine/wined3d/stateblock.c | 119 +- reactos/dll/directx/wine/wined3d/surface.c | 1752 +++++-- .../dll/directx/wine/wined3d/surface_base.c | 539 +- .../dll/directx/wine/wined3d/surface_gdi.c | 318 +- reactos/dll/directx/wine/wined3d/swapchain.c | 370 +- .../dll/directx/wine/wined3d/swapchain_base.c | 191 + .../dll/directx/wine/wined3d/swapchain_gdi.c | 272 ++ reactos/dll/directx/wine/wined3d/texture.c | 91 +- reactos/dll/directx/wine/wined3d/utils.c | 2359 +++------ .../dll/directx/wine/wined3d/vertexbuffer.c | 620 ++- .../directx/wine/wined3d/vertexdeclaration.c | 25 +- .../dll/directx/wine/wined3d/vertexshader.c | 175 +- reactos/dll/directx/wine/wined3d/volume.c | 50 +- .../dll/directx/wine/wined3d/volumetexture.c | 48 +- .../dll/directx/wine/wined3d/wined3d.rbuild | 4 + .../dll/directx/wine/wined3d/wined3d_main.c | 14 +- .../directx/wine/wined3d/wined3d_private.h | 648 ++- .../wine/wined3d/wined3d_private_types.h | 12 +- reactos/include/psdk/d3d9.h | 513 ++ reactos/include/psdk/d3d9types.h | 43 + reactos/include/reactos/wine/wined3d_caps.h | 141 + reactos/include/reactos/wine/wined3d_gl.h | 835 ++-- .../include/reactos/wine/wined3d_interface.h | 75 +- reactos/include/reactos/wine/wined3d_types.h | 222 +- 66 files changed, 19223 insertions(+), 9041 deletions(-) create mode 100644 reactos/dll/directx/wine/wined3d/ati_fragment_shader.c create mode 100644 reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c create mode 100644 reactos/dll/directx/wine/wined3d/swapchain_base.c create mode 100644 reactos/dll/directx/wine/wined3d/swapchain_gdi.c diff --git a/reactos/dll/directx/wine/d3d8/d3d8_main.c b/reactos/dll/directx/wine/d3d8/d3d8_main.c index 63cb47204d5..56de60daba7 100644 --- a/reactos/dll/directx/wine/d3d8/d3d8_main.c +++ b/reactos/dll/directx/wine/d3d8/d3d8_main.c @@ -58,6 +58,11 @@ IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion) { TRACE("Created Direct3D object @ %p, WineObj @ %p\n", object, object->WineD3D); LeaveCriticalSection(&d3d8_cs); + if (!object->WineD3D) + { + HeapFree( GetProcessHeap(), 0, object ); + object = NULL; + } return (IDirect3D8*) object; } diff --git a/reactos/dll/directx/wine/d3d8/d3d8_private.h b/reactos/dll/directx/wine/d3d8/d3d8_private.h index 229762b9957..86adcbac1cc 100644 --- a/reactos/dll/directx/wine/d3d8/d3d8_private.h +++ b/reactos/dll/directx/wine/d3d8/d3d8_private.h @@ -45,60 +45,60 @@ Macros =========================================================================== */ /* Not nice, but it lets wined3d support different versions of directx */ -#define D3D8CAPSTOWINECAPS(_pD3D8Caps, _pWineCaps) \ - _pWineCaps->DeviceType = (WINED3DDEVTYPE *) &_pD3D8Caps->DeviceType; \ - _pWineCaps->AdapterOrdinal = &_pD3D8Caps->AdapterOrdinal; \ - _pWineCaps->Caps = &_pD3D8Caps->Caps; \ - _pWineCaps->Caps2 = &_pD3D8Caps->Caps2; \ - _pWineCaps->Caps3 = &_pD3D8Caps->Caps3; \ - _pWineCaps->PresentationIntervals = &_pD3D8Caps->PresentationIntervals; \ - _pWineCaps->CursorCaps = &_pD3D8Caps->CursorCaps; \ - _pWineCaps->DevCaps = &_pD3D8Caps->DevCaps; \ - _pWineCaps->PrimitiveMiscCaps = &_pD3D8Caps->PrimitiveMiscCaps; \ - _pWineCaps->RasterCaps = &_pD3D8Caps->RasterCaps; \ - _pWineCaps->ZCmpCaps = &_pD3D8Caps->ZCmpCaps; \ - _pWineCaps->SrcBlendCaps = &_pD3D8Caps->SrcBlendCaps; \ - _pWineCaps->DestBlendCaps = &_pD3D8Caps->DestBlendCaps; \ - _pWineCaps->AlphaCmpCaps = &_pD3D8Caps->AlphaCmpCaps; \ - _pWineCaps->ShadeCaps = &_pD3D8Caps->ShadeCaps; \ - _pWineCaps->TextureCaps = &_pD3D8Caps->TextureCaps; \ - _pWineCaps->TextureFilterCaps = &_pD3D8Caps->TextureFilterCaps; \ - _pWineCaps->CubeTextureFilterCaps = &_pD3D8Caps->CubeTextureFilterCaps; \ - _pWineCaps->VolumeTextureFilterCaps = &_pD3D8Caps->VolumeTextureFilterCaps; \ - _pWineCaps->TextureAddressCaps = &_pD3D8Caps->TextureAddressCaps; \ - _pWineCaps->VolumeTextureAddressCaps = &_pD3D8Caps->VolumeTextureAddressCaps; \ - _pWineCaps->LineCaps = &_pD3D8Caps->LineCaps; \ - _pWineCaps->MaxTextureWidth = &_pD3D8Caps->MaxTextureWidth; \ - _pWineCaps->MaxTextureHeight = &_pD3D8Caps->MaxTextureHeight; \ - _pWineCaps->MaxVolumeExtent = &_pD3D8Caps->MaxVolumeExtent; \ - _pWineCaps->MaxTextureRepeat = &_pD3D8Caps->MaxTextureRepeat; \ - _pWineCaps->MaxTextureAspectRatio = &_pD3D8Caps->MaxTextureAspectRatio; \ - _pWineCaps->MaxAnisotropy = &_pD3D8Caps->MaxAnisotropy; \ - _pWineCaps->MaxVertexW = &_pD3D8Caps->MaxVertexW; \ - _pWineCaps->GuardBandLeft = &_pD3D8Caps->GuardBandLeft; \ - _pWineCaps->GuardBandTop = &_pD3D8Caps->GuardBandTop; \ - _pWineCaps->GuardBandRight = &_pD3D8Caps->GuardBandRight; \ - _pWineCaps->GuardBandBottom = &_pD3D8Caps->GuardBandBottom; \ - _pWineCaps->ExtentsAdjust = &_pD3D8Caps->ExtentsAdjust; \ - _pWineCaps->StencilCaps = &_pD3D8Caps->StencilCaps; \ - _pWineCaps->FVFCaps = &_pD3D8Caps->FVFCaps; \ - _pWineCaps->TextureOpCaps = &_pD3D8Caps->TextureOpCaps; \ - _pWineCaps->MaxTextureBlendStages = &_pD3D8Caps->MaxTextureBlendStages; \ - _pWineCaps->MaxSimultaneousTextures = &_pD3D8Caps->MaxSimultaneousTextures; \ - _pWineCaps->VertexProcessingCaps = &_pD3D8Caps->VertexProcessingCaps; \ - _pWineCaps->MaxActiveLights = &_pD3D8Caps->MaxActiveLights; \ - _pWineCaps->MaxUserClipPlanes = &_pD3D8Caps->MaxUserClipPlanes; \ - _pWineCaps->MaxVertexBlendMatrices = &_pD3D8Caps->MaxVertexBlendMatrices; \ - _pWineCaps->MaxVertexBlendMatrixIndex = &_pD3D8Caps->MaxVertexBlendMatrixIndex; \ - _pWineCaps->MaxPointSize = &_pD3D8Caps->MaxPointSize; \ - _pWineCaps->MaxPrimitiveCount = &_pD3D8Caps->MaxPrimitiveCount; \ - _pWineCaps->MaxVertexIndex = &_pD3D8Caps->MaxVertexIndex; \ - _pWineCaps->MaxStreams = &_pD3D8Caps->MaxStreams; \ - _pWineCaps->MaxStreamStride = &_pD3D8Caps->MaxStreamStride; \ - _pWineCaps->VertexShaderVersion = &_pD3D8Caps->VertexShaderVersion; \ - _pWineCaps->MaxVertexShaderConst = &_pD3D8Caps->MaxVertexShaderConst; \ - _pWineCaps->PixelShaderVersion = &_pD3D8Caps->PixelShaderVersion; \ - _pWineCaps->PixelShader1xMaxValue = &_pD3D8Caps->MaxPixelShaderValue; +#define WINECAPSTOD3D8CAPS(_pD3D8Caps, _pWineCaps) \ + _pD3D8Caps->DeviceType = (D3DDEVTYPE) _pWineCaps->DeviceType; \ + _pD3D8Caps->AdapterOrdinal = _pWineCaps->AdapterOrdinal; \ + _pD3D8Caps->Caps = _pWineCaps->Caps; \ + _pD3D8Caps->Caps2 = _pWineCaps->Caps2; \ + _pD3D8Caps->Caps3 = _pWineCaps->Caps3; \ + _pD3D8Caps->PresentationIntervals = _pWineCaps->PresentationIntervals; \ + _pD3D8Caps->CursorCaps = _pWineCaps->CursorCaps; \ + _pD3D8Caps->DevCaps = _pWineCaps->DevCaps; \ + _pD3D8Caps->PrimitiveMiscCaps = _pWineCaps->PrimitiveMiscCaps; \ + _pD3D8Caps->RasterCaps = _pWineCaps->RasterCaps; \ + _pD3D8Caps->ZCmpCaps = _pWineCaps->ZCmpCaps; \ + _pD3D8Caps->SrcBlendCaps = _pWineCaps->SrcBlendCaps; \ + _pD3D8Caps->DestBlendCaps = _pWineCaps->DestBlendCaps; \ + _pD3D8Caps->AlphaCmpCaps = _pWineCaps->AlphaCmpCaps; \ + _pD3D8Caps->ShadeCaps = _pWineCaps->ShadeCaps; \ + _pD3D8Caps->TextureCaps = _pWineCaps->TextureCaps; \ + _pD3D8Caps->TextureFilterCaps = _pWineCaps->TextureFilterCaps; \ + _pD3D8Caps->CubeTextureFilterCaps = _pWineCaps->CubeTextureFilterCaps; \ + _pD3D8Caps->VolumeTextureFilterCaps = _pWineCaps->VolumeTextureFilterCaps; \ + _pD3D8Caps->TextureAddressCaps = _pWineCaps->TextureAddressCaps; \ + _pD3D8Caps->VolumeTextureAddressCaps = _pWineCaps->VolumeTextureAddressCaps; \ + _pD3D8Caps->LineCaps = _pWineCaps->LineCaps; \ + _pD3D8Caps->MaxTextureWidth = _pWineCaps->MaxTextureWidth; \ + _pD3D8Caps->MaxTextureHeight = _pWineCaps->MaxTextureHeight; \ + _pD3D8Caps->MaxVolumeExtent = _pWineCaps->MaxVolumeExtent; \ + _pD3D8Caps->MaxTextureRepeat = _pWineCaps->MaxTextureRepeat; \ + _pD3D8Caps->MaxTextureAspectRatio = _pWineCaps->MaxTextureAspectRatio; \ + _pD3D8Caps->MaxAnisotropy = _pWineCaps->MaxAnisotropy; \ + _pD3D8Caps->MaxVertexW = _pWineCaps->MaxVertexW; \ + _pD3D8Caps->GuardBandLeft = _pWineCaps->GuardBandLeft; \ + _pD3D8Caps->GuardBandTop = _pWineCaps->GuardBandTop; \ + _pD3D8Caps->GuardBandRight = _pWineCaps->GuardBandRight; \ + _pD3D8Caps->GuardBandBottom = _pWineCaps->GuardBandBottom; \ + _pD3D8Caps->ExtentsAdjust = _pWineCaps->ExtentsAdjust; \ + _pD3D8Caps->StencilCaps = _pWineCaps->StencilCaps; \ + _pD3D8Caps->FVFCaps = _pWineCaps->FVFCaps; \ + _pD3D8Caps->TextureOpCaps = _pWineCaps->TextureOpCaps; \ + _pD3D8Caps->MaxTextureBlendStages = _pWineCaps->MaxTextureBlendStages; \ + _pD3D8Caps->MaxSimultaneousTextures = _pWineCaps->MaxSimultaneousTextures; \ + _pD3D8Caps->VertexProcessingCaps = _pWineCaps->VertexProcessingCaps; \ + _pD3D8Caps->MaxActiveLights = _pWineCaps->MaxActiveLights; \ + _pD3D8Caps->MaxUserClipPlanes = _pWineCaps->MaxUserClipPlanes; \ + _pD3D8Caps->MaxVertexBlendMatrices = _pWineCaps->MaxVertexBlendMatrices; \ + _pD3D8Caps->MaxVertexBlendMatrixIndex = _pWineCaps->MaxVertexBlendMatrixIndex; \ + _pD3D8Caps->MaxPointSize = _pWineCaps->MaxPointSize; \ + _pD3D8Caps->MaxPrimitiveCount = _pWineCaps->MaxPrimitiveCount; \ + _pD3D8Caps->MaxVertexIndex = _pWineCaps->MaxVertexIndex; \ + _pD3D8Caps->MaxStreams = _pWineCaps->MaxStreams; \ + _pD3D8Caps->MaxStreamStride = _pWineCaps->MaxStreamStride; \ + _pD3D8Caps->VertexShaderVersion = _pWineCaps->VertexShaderVersion; \ + _pD3D8Caps->MaxVertexShaderConst = _pWineCaps->MaxVertexShaderConst; \ + _pD3D8Caps->PixelShaderVersion = _pWineCaps->PixelShaderVersion; \ + _pD3D8Caps->MaxPixelShaderValue = _pWineCaps->PixelShader1xMaxValue; /* Direct3D8 Interfaces: */ typedef struct IDirect3DBaseTexture8Impl IDirect3DBaseTexture8Impl; @@ -127,7 +127,7 @@ typedef struct IDirect3DVertexShader8Impl IDirect3DVertexShader8Impl; extern CRITICAL_SECTION d3d8_cs; /* =========================================================================== - The interfactes themselves + The interfaces themselves =========================================================================== */ /* ---------- */ @@ -600,7 +600,7 @@ struct IDirect3DVertexShader8Impl { const IDirect3DVertexShader8Vtbl *lpVtbl; LONG ref; - shader_handle *handle; + DWORD handle; IDirect3DVertexDeclaration8 *vertex_declaration; IWineD3DVertexShader *wineD3DVertexShader; }; @@ -623,7 +623,7 @@ typedef struct IDirect3DPixelShader8Impl { const IDirect3DPixelShader8Vtbl *lpVtbl; LONG ref; - shader_handle *handle; + DWORD handle; /* The device, to be replaced by an IDirect3DDeviceImpl */ IWineD3DPixelShader *wineD3DPixelShader; } IDirect3DPixelShader8Impl; @@ -634,7 +634,8 @@ typedef struct IDirect3DPixelShader8Impl { * to see how not defined it here */ void load_local_constants(const DWORD *d3d8_elements, IWineD3DVertexShader *wined3d_vertex_shader); -size_t convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, WINED3DVERTEXELEMENT **wined3d_elements); +UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, WINED3DVERTEXELEMENT **wined3d_elements); +size_t parse_token(const DWORD* pToken); /* Callbacks */ extern HRESULT WINAPI D3D8CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT Width, UINT Height, diff --git a/reactos/dll/directx/wine/d3d8/device.c b/reactos/dll/directx/wine/d3d8/device.c index 55ebe83f4bb..976d7dd31c5 100644 --- a/reactos/dll/directx/wine/d3d8/device.c +++ b/reactos/dll/directx/wine/d3d8/device.c @@ -97,7 +97,7 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - int i; + unsigned i; TRACE("Releasing wined3d device %p\n", This->WineD3DDevice); EnterCriticalSection(&d3d8_cs); @@ -192,10 +192,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */ } - D3D8CAPSTOWINECAPS(pCaps, pWineCaps) EnterCriticalSection(&d3d8_cs); hrc = IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pWineCaps); LeaveCriticalSection(&d3d8_cs); + WINECAPSTOD3D8CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ @@ -243,7 +243,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 } EnterCriticalSection(&d3d8_cs); - hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice,XHotSpot,YHotSpot,(IWineD3DSurface*)pSurface->wineD3DSurface); + hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice,XHotSpot,YHotSpot,pSurface->wineD3DSurface); LeaveCriticalSection(&d3d8_cs); return hr; } @@ -307,7 +307,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DD localParameters.PresentationInterval = pPresentationParameters->FullScreen_PresentationInterval; EnterCriticalSection(&d3d8_cs); - hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface); + hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface, SURFACE_OPENGL); LeaveCriticalSection(&d3d8_cs); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; @@ -399,7 +399,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface TRACE("(%p) Relay\n", This); EnterCriticalSection(&d3d8_cs); - rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, 0, BackBuffer, (WINED3DBACKBUFFER_TYPE) Type, (IWineD3DSurface **)&retSurface); + rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, 0, BackBuffer, (WINED3DBACKBUFFER_TYPE) Type, &retSurface); if (rc == D3D_OK && NULL != retSurface && NULL != ppBackBuffer) { IWineD3DSurface_GetParent(retSurface, (IUnknown **)ppBackBuffer); IWineD3DSurface_Release(retSurface); @@ -472,9 +472,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface IUnknown_AddRef(iface); object->parentDevice = iface; *ppTexture = (LPDIRECT3DTEXTURE8) object; + TRACE("(%p) Created Texture %p, %p\n",This,object,object->wineD3DTexture); } - TRACE("(%p) Created Texture %p, %p\n",This,object,object->wineD3DTexture); return hrc; } @@ -635,11 +635,6 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface IDirect3DSurface8Impl *object; IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; TRACE("(%p) Relay\n", This); - if(MultisampleQuality < 0) { - FIXME("MultisampleQuality out of range %d, substituting 0\n", MultisampleQuality); - /*FIXME: Find out what windows does with a MultisampleQuality < 0 */ - MultisampleQuality=0; - } if(MultisampleQuality > 0){ FIXME("MultisampleQuality set to %d, substituting 0\n" , MultisampleQuality); @@ -702,12 +697,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DD return hr; } +/* IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */ static HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) { HRESULT hr; TRACE("Relay\n"); EnterCriticalSection(&d3d8_cs); - hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Loackable */ , FALSE /*Discard*/ , 0 /* Level */ , ppSurface, D3DRTYPE_SURFACE, 0 /* Usage (undefined/none) */ , D3DPOOL_SCRATCH, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */); + hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Loackable */ , FALSE /*Discard*/ , 0 /* Level */ , ppSurface, + D3DRTYPE_SURFACE, 0 /* Usage (undefined/none) */ , D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */); LeaveCriticalSection(&d3d8_cs); return hr; } @@ -808,13 +805,22 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 ifa IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; IDirect3DSurface8Impl *pSurface = (IDirect3DSurface8Impl *)pRenderTarget; IDirect3DSurface8Impl *pZSurface = (IDirect3DSurface8Impl *)pNewZStencil; + IWineD3DSurface *original_ds = NULL; HRESULT hr; TRACE("(%p) Relay\n" , This); - IWineD3DDevice_SetDepthStencilSurface(This->WineD3DDevice, NULL == pZSurface ? NULL : (IWineD3DSurface *)pZSurface->wineD3DSurface); - EnterCriticalSection(&d3d8_cs); - hr = IWineD3DDevice_SetRenderTarget(This->WineD3DDevice, 0, pSurface ? (IWineD3DSurface *)pSurface->wineD3DSurface : NULL); + + hr = IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice, &original_ds); + if (hr == WINED3D_OK || hr == WINED3DERR_NOTFOUND) + { + hr = IWineD3DDevice_SetDepthStencilSurface(This->WineD3DDevice, pZSurface ? pZSurface->wineD3DSurface : NULL); + if (SUCCEEDED(hr) && pSurface) + hr = IWineD3DDevice_SetRenderTarget(This->WineD3DDevice, 0, pSurface->wineD3DSurface); + if (FAILED(hr)) IWineD3DDevice_SetDepthStencilSurface(This->WineD3DDevice, original_ds); + } + if (original_ds) IWineD3DSurface_Release(original_ds); + LeaveCriticalSection(&d3d8_cs); return hr; } @@ -856,16 +862,17 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDE EnterCriticalSection(&d3d8_cs); hr=IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice,&pZStencilSurface); - if(hr == D3D_OK && pZStencilSurface != NULL){ + if (hr == WINED3D_OK) { IWineD3DSurface_GetParent(pZStencilSurface,(IUnknown**)ppZStencilSurface); IWineD3DSurface_Release(pZStencilSurface); }else{ - FIXME("Call to IWineD3DDevice_GetDepthStencilSurface failed\n"); + if (hr != WINED3DERR_NOTFOUND) + FIXME("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr); *ppZStencilSurface = NULL; } LeaveCriticalSection(&d3d8_cs); - return D3D_OK; + return hr; } static HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) { @@ -1095,7 +1102,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface TRACE("(%p) Relay\n", This); - /* Tell wineD3D to endstatablock before anything else (in case we run out + /* Tell wineD3D to endstateblock before anything else (in case we run out * of memory later and cause locking problems) */ EnterCriticalSection(&d3d8_cs); @@ -1189,8 +1196,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 if *pToken = 0; } else { *pToken = (DWORD)object; + TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object); } - TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object); return hrc; } @@ -1229,7 +1236,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, D } EnterCriticalSection(&d3d8_cs); - rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, (IWineD3DBaseTexture **)&retTexture); + rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, &retTexture); if (rc == D3D_OK && NULL != retTexture) { IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); IWineD3DBaseTexture_Release(retTexture); @@ -1477,7 +1484,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexDeclaration(IDirect3DDevi IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; IDirect3DVertexDeclaration8Impl *object; WINED3DVERTEXELEMENT *wined3d_elements; - size_t wined3d_element_count; + UINT wined3d_element_count; HRESULT hr = D3D_OK; TRACE("(%p) : declaration %p\n", This, declaration); @@ -1527,6 +1534,23 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 HRESULT hrc = D3D_OK; IDirect3DVertexShader8Impl *object; IWineD3DVertexDeclaration *wined3d_vertex_declaration; + const DWORD *token = pDeclaration; + + /* Test if the vertex declaration is valid */ + while (D3DVSD_END() != *token) { + D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); + + if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) { + DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); + DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); + + if(reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !pFunction) { + WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n"); + return D3DERR_INVALIDCALL; + } + } + token += parse_token(token); + } /* Setup a stub object for now */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); @@ -1560,22 +1584,22 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 HeapFree(GetProcessHeap(), 0, object); *ppShader = 0; } else { - /* TODO: Store the VS declarations locally so that they can be derefferenced with a value higher than VS_HIGHESTFIXEDFXF */ + /* TODO: Store the VS declarations locally so that they can be dereferenced with a value higher than VS_HIGHESTFIXEDFXF */ shader_handle *handle = alloc_shader_handle(This); if (!handle) { ERR("Failed to allocate shader handle\n"); IDirect3DVertexShader8_Release((IUnknown *)object); hrc = E_OUTOFMEMORY; } else { - object->handle = handle; *handle = object; - *ppShader = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1; + object->handle = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1; + *ppShader = object->handle; load_local_constants(pDeclaration, object->wineD3DVertexShader); + TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); } } LeaveCriticalSection(&d3d8_cs); - TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); return hrc; } @@ -1675,7 +1699,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 ifa IDirect3DVertexShader8Impl *d3d8_shader; hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)&d3d8_shader); IWineD3DVertexShader_Release(pShader); - *ppShader = (d3d8_shader->handle - This->shader_handles) + (VS_HIGHESTFIXEDFXF + 1); + *ppShader = d3d8_shader->handle; } else { *ppShader = 0; hrc = D3D_OK; @@ -1793,7 +1817,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEV } shader = This->shader_handles[pVertexShader - (VS_HIGHESTFIXEDFXF + 1)]; - hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, (UINT *)pSizeOfData); + hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData); LeaveCriticalSection(&d3d8_cs); return hr; } @@ -1875,15 +1899,15 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 i IDirect3DVertexShader8_Release((IUnknown *)object); hrc = E_OUTOFMEMORY; } else { - object->handle = handle; *handle = object; - *ppShader = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1; + object->handle = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1; + *ppShader = object->handle; + TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); } } LeaveCriticalSection(&d3d8_cs); } - TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader); return hrc; } @@ -1924,7 +1948,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 ifac IDirect3DPixelShader8Impl *d3d8_shader; hrc = IWineD3DPixelShader_GetParent(object, (IUnknown **)&d3d8_shader); IWineD3DPixelShader_Release(object); - *ppShader = (d3d8_shader->handle - This->shader_handles) + (VS_HIGHESTFIXEDFXF + 1); + *ppShader = d3d8_shader->handle; } else { *ppShader = (DWORD)NULL; } @@ -2000,7 +2024,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVI } shader = This->shader_handles[pPixelShader - (VS_HIGHESTFIXEDFXF + 1)]; - hr = IWineD3DPixelShader_GetFunction(shader->wineD3DPixelShader, pData, (UINT *)pSizeOfData); + hr = IWineD3DPixelShader_GetFunction(shader->wineD3DPixelShader, pData, pSizeOfData); LeaveCriticalSection(&d3d8_cs); return hr; } @@ -2063,7 +2087,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 ifa } EnterCriticalSection(&d3d8_cs); - rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, (IWineD3DVertexBuffer **)&retStream, 0 /* Offset in bytes */, pStride); + rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, &retStream, 0 /* Offset in bytes */, pStride); if (rc == D3D_OK && NULL != retStream) { IWineD3DVertexBuffer_GetParent(retStream, (IUnknown **)pStream); IWineD3DVertexBuffer_Release(retStream); diff --git a/reactos/dll/directx/wine/d3d8/directx.c b/reactos/dll/directx/wine/d3d8/directx.c index 54c87e68484..afcb0fe38d5 100644 --- a/reactos/dll/directx/wine/d3d8/directx.c +++ b/reactos/dll/directx/wine/d3d8/directx.c @@ -184,7 +184,7 @@ static HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 i EnterCriticalSection(&d3d8_cs); hr = IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, AdapterFormat, - Usage, RType, CheckFormat); + Usage, RType, CheckFormat, SURFACE_OPENGL); LeaveCriticalSection(&d3d8_cs); return hr; } @@ -231,10 +231,10 @@ static HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Ada if(pWineCaps == NULL){ return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/ } - D3D8CAPSTOWINECAPS(pCaps, pWineCaps) EnterCriticalSection(&d3d8_cs); hrc = IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, pWineCaps); LeaveCriticalSection(&d3d8_cs); + WINECAPSTOD3D8CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ @@ -295,7 +295,7 @@ ULONG WINAPI D3D8CB_DestroyRenderTarget(IWineD3DSurface *pSurface) { return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent); } -/* Callback for creating the inplicite swapchain when the device is created */ +/* Callback for creating the implicit swapchain when the device is created */ static HRESULT WINAPI D3D8CB_CreateAdditionalSwapChain(IUnknown *device, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain ** ppSwapChain){ diff --git a/reactos/dll/directx/wine/d3d8/stateblock.c b/reactos/dll/directx/wine/d3d8/stateblock.c index d42fb79f889..ac2cdbe9982 100644 --- a/reactos/dll/directx/wine/d3d8/stateblock.c +++ b/reactos/dll/directx/wine/d3d8/stateblock.c @@ -25,7 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d8); -/* NOTE: DirectX8 doesn't export a IDirect3DStateBlock8, the interface is used internally to keep d3d8 and d3d9 as simila as possible */ +/* NOTE: DirectX8 doesn't export an IDirect3DStateBlock8, the interface is used internally to keep d3d8 and d3d9 as similar as possible */ /* IDirect3DStateBlock8 IUnknown parts follow: */ static HRESULT WINAPI IDirect3DStateBlock8Impl_QueryInterface(IDirect3DStateBlock8 *iface, REFIID riid, LPVOID *ppobj) { IDirect3DStateBlock8Impl *This = (IDirect3DStateBlock8Impl *)iface; diff --git a/reactos/dll/directx/wine/d3d8/vertexdeclaration.c b/reactos/dll/directx/wine/d3d8/vertexdeclaration.c index 3a53c1179d8..debeca0c52a 100644 --- a/reactos/dll/directx/wine/d3d8/vertexdeclaration.c +++ b/reactos/dll/directx/wine/d3d8/vertexdeclaration.c @@ -118,7 +118,7 @@ static const char *debug_d3dvsde_register(D3DVSDE_REGISTER d3dvsde_register) } } -static size_t parse_token(const DWORD* pToken) +size_t parse_token(const DWORD* pToken) { const DWORD token = *pToken; size_t tokenlen = 1; @@ -272,7 +272,7 @@ static const wined3d_usage_t wined3d_usage_lookup[] = { }; /* TODO: find out where rhw (or positionT) is for declaration8 */ -size_t convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, WINED3DVERTEXELEMENT **wined3d_elements) +UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, WINED3DVERTEXELEMENT **wined3d_elements) { const DWORD *token = d3d8_elements; WINED3DVERTEXELEMENT *element; diff --git a/reactos/dll/directx/wine/d3d8/volume.c b/reactos/dll/directx/wine/d3d8/volume.c index bea2ea9f8bc..e37817aceae 100644 --- a/reactos/dll/directx/wine/d3d8/volume.c +++ b/reactos/dll/directx/wine/d3d8/volume.c @@ -237,7 +237,7 @@ HRESULT WINAPI D3D8CB_CreateVolume(IUnknown *pDevice, IUnknown *pSuperior, UINT HeapFree(GetProcessHeap(), 0, object); *ppVolume = NULL; } else { - *ppVolume = (IWineD3DVolume *)object->wineD3DVolume; + *ppVolume = object->wineD3DVolume; object->container = pSuperior; object->forwardReference = pSuperior; } diff --git a/reactos/dll/directx/wine/d3d9/Makefile.in b/reactos/dll/directx/wine/d3d9/Makefile.in index 904dda9923c..f581b68eb8c 100644 --- a/reactos/dll/directx/wine/d3d9/Makefile.in +++ b/reactos/dll/directx/wine/d3d9/Makefile.in @@ -3,9 +3,8 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = d3d9.dll -IMPORTLIB = libd3d9.$(IMPLIBEXT) -IMPORTS = wined3d user32 gdi32 kernel32 -EXTRALIBS = -ldxguid -luuid +IMPORTLIB = d3d9 +IMPORTS = dxguid uuid wined3d kernel32 C_SRCS = \ basetexture.c \ diff --git a/reactos/dll/directx/wine/d3d9/cubetexture.c b/reactos/dll/directx/wine/d3d9/cubetexture.c index 0ea378bc29d..9369fa5a7bb 100644 --- a/reactos/dll/directx/wine/d3d9/cubetexture.c +++ b/reactos/dll/directx/wine/d3d9/cubetexture.c @@ -333,7 +333,7 @@ static const IDirect3DCubeTexture9Vtbl Direct3DCubeTexture9_Vtbl = /* IDirect3DDevice9 IDirect3DCubeTexture9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9 iface, +HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9EX iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) { diff --git a/reactos/dll/directx/wine/d3d9/d3d9.spec b/reactos/dll/directx/wine/d3d9/d3d9.spec index 949f03fb09b..a33cba51e77 100644 --- a/reactos/dll/directx/wine/d3d9/d3d9.spec +++ b/reactos/dll/directx/wine/d3d9/d3d9.spec @@ -1,10 +1,14 @@ -@ stdcall D3D9GetSWInfo() -@ stdcall DebugSetMute() -@ stdcall Direct3DCreate9(long) +@ stdcall Direct3DShaderValidatorCreate9() +@ stub PSGPError +@ stub PSGPSampleTexture @ stdcall D3DPERF_BeginEvent(long wstr) @ stdcall D3DPERF_EndEvent() @ stdcall D3DPERF_GetStatus() -@ stdcall D3DPERF_SetOptions(long) @ stdcall D3DPERF_QueryRepeatFrame() @ stdcall D3DPERF_SetMarker(long wstr) +@ stdcall D3DPERF_SetOptions(long) @ stdcall D3DPERF_SetRegion(long wstr) +@ stub DebugSetLevel +@ stdcall DebugSetMute() +@ stdcall Direct3DCreate9(long) +@ stdcall Direct3DCreate9Ex(long ptr) diff --git a/reactos/dll/directx/wine/d3d9/d3d9_main.c b/reactos/dll/directx/wine/d3d9/d3d9_main.c index ba4da662aa4..03c75a473f3 100644 --- a/reactos/dll/directx/wine/d3d9/d3d9_main.c +++ b/reactos/dll/directx/wine/d3d9/d3d9_main.c @@ -38,11 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d9); static int D3DPERF_event_level = 0; -HRESULT WINAPI D3D9GetSWInfo(void) { - FIXME("(void): stub\n"); - return 0; -} - void WINAPI DebugSetMute(void) { /* nothing to do */ } @@ -58,12 +53,49 @@ IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) { TRACE("SDKVersion = %x, Created Direct3D object @ %p, WineObj @ %p\n", SDKVersion, object, object->WineD3D); + if (!object->WineD3D) + { + HeapFree( GetProcessHeap(), 0, object ); + object = NULL; + } return (IDirect3D9*) object; } -/* At process attach */ +HRESULT WINAPI Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex **direct3d9ex) { + IDirect3D9 *ret; + IDirect3D9Impl* object; + + TRACE("Calling Direct3DCreate9\n"); + ret = Direct3DCreate9(SDKVersion); + if(!ret) { + *direct3d9ex = NULL; + return D3DERR_NOTAVAILABLE; + } + + object = (IDirect3D9Impl *) ret; + object->extended = TRUE; /* Enables QI for extended interfaces */ + *direct3d9ex = (IDirect3D9Ex *) object; + return D3D_OK; +} + +/******************************************************************* + * Direct3DShaderValidatorCreate9 (D3D9.@) + * + * No documentation available for this function. + * SDK only says it is internal and shouldn't be used. + */ +void* WINAPI Direct3DShaderValidatorCreate9(void) +{ + FIXME("stub\n"); + return NULL; +} + +/******************************************************************* + * DllMain + */ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) { + /* At process attach */ TRACE("fdwReason=%d\n", fdwReason); if (fdwReason == DLL_PROCESS_ATTACH) DisableThreadLibraryCalls(hInstDLL); diff --git a/reactos/dll/directx/wine/d3d9/d3d9_private.h b/reactos/dll/directx/wine/d3d9/d3d9_private.h index 160cb673999..03c4d47fd94 100644 --- a/reactos/dll/directx/wine/d3d9/d3d9_private.h +++ b/reactos/dll/directx/wine/d3d9/d3d9_private.h @@ -50,86 +50,86 @@ extern CRITICAL_SECTION d3d9_cs; Macros =========================================================================== */ /* Not nice, but it lets wined3d support different versions of directx */ -#define D3D9CAPSTOWINECAPS(_pD3D9Caps, _pWineCaps) \ - _pWineCaps->DeviceType = (WINED3DDEVTYPE *) &_pD3D9Caps->DeviceType; \ - _pWineCaps->AdapterOrdinal = &_pD3D9Caps->AdapterOrdinal; \ - _pWineCaps->Caps = &_pD3D9Caps->Caps; \ - _pWineCaps->Caps2 = &_pD3D9Caps->Caps2; \ - _pWineCaps->Caps3 = &_pD3D9Caps->Caps3; \ - _pWineCaps->PresentationIntervals = &_pD3D9Caps->PresentationIntervals; \ - _pWineCaps->CursorCaps = &_pD3D9Caps->CursorCaps; \ - _pWineCaps->DevCaps = &_pD3D9Caps->DevCaps; \ - _pWineCaps->PrimitiveMiscCaps = &_pD3D9Caps->PrimitiveMiscCaps; \ - _pWineCaps->RasterCaps = &_pD3D9Caps->RasterCaps; \ - _pWineCaps->ZCmpCaps = &_pD3D9Caps->ZCmpCaps; \ - _pWineCaps->SrcBlendCaps = &_pD3D9Caps->SrcBlendCaps; \ - _pWineCaps->DestBlendCaps = &_pD3D9Caps->DestBlendCaps; \ - _pWineCaps->AlphaCmpCaps = &_pD3D9Caps->AlphaCmpCaps; \ - _pWineCaps->ShadeCaps = &_pD3D9Caps->ShadeCaps; \ - _pWineCaps->TextureCaps = &_pD3D9Caps->TextureCaps; \ - _pWineCaps->TextureFilterCaps = &_pD3D9Caps->TextureFilterCaps; \ - _pWineCaps->CubeTextureFilterCaps = &_pD3D9Caps->CubeTextureFilterCaps; \ - _pWineCaps->VolumeTextureFilterCaps = &_pD3D9Caps->VolumeTextureFilterCaps; \ - _pWineCaps->TextureAddressCaps = &_pD3D9Caps->TextureAddressCaps; \ - _pWineCaps->VolumeTextureAddressCaps = &_pD3D9Caps->VolumeTextureAddressCaps; \ - _pWineCaps->LineCaps = &_pD3D9Caps->LineCaps; \ - _pWineCaps->MaxTextureWidth = &_pD3D9Caps->MaxTextureWidth; \ - _pWineCaps->MaxTextureHeight = &_pD3D9Caps->MaxTextureHeight; \ - _pWineCaps->MaxVolumeExtent = &_pD3D9Caps->MaxVolumeExtent; \ - _pWineCaps->MaxTextureRepeat = &_pD3D9Caps->MaxTextureRepeat; \ - _pWineCaps->MaxTextureAspectRatio = &_pD3D9Caps->MaxTextureAspectRatio; \ - _pWineCaps->MaxAnisotropy = &_pD3D9Caps->MaxAnisotropy; \ - _pWineCaps->MaxVertexW = &_pD3D9Caps->MaxVertexW; \ - _pWineCaps->GuardBandLeft = &_pD3D9Caps->GuardBandLeft; \ - _pWineCaps->GuardBandTop = &_pD3D9Caps->GuardBandTop; \ - _pWineCaps->GuardBandRight = &_pD3D9Caps->GuardBandRight; \ - _pWineCaps->GuardBandBottom = &_pD3D9Caps->GuardBandBottom; \ - _pWineCaps->ExtentsAdjust = &_pD3D9Caps->ExtentsAdjust; \ - _pWineCaps->StencilCaps = &_pD3D9Caps->StencilCaps; \ - _pWineCaps->FVFCaps = &_pD3D9Caps->FVFCaps; \ - _pWineCaps->TextureOpCaps = &_pD3D9Caps->TextureOpCaps; \ - _pWineCaps->MaxTextureBlendStages = &_pD3D9Caps->MaxTextureBlendStages; \ - _pWineCaps->MaxSimultaneousTextures = &_pD3D9Caps->MaxSimultaneousTextures; \ - _pWineCaps->VertexProcessingCaps = &_pD3D9Caps->VertexProcessingCaps; \ - _pWineCaps->MaxActiveLights = &_pD3D9Caps->MaxActiveLights; \ - _pWineCaps->MaxUserClipPlanes = &_pD3D9Caps->MaxUserClipPlanes; \ - _pWineCaps->MaxVertexBlendMatrices = &_pD3D9Caps->MaxVertexBlendMatrices; \ - _pWineCaps->MaxVertexBlendMatrixIndex = &_pD3D9Caps->MaxVertexBlendMatrixIndex; \ - _pWineCaps->MaxPointSize = &_pD3D9Caps->MaxPointSize; \ - _pWineCaps->MaxPrimitiveCount = &_pD3D9Caps->MaxPrimitiveCount; \ - _pWineCaps->MaxVertexIndex = &_pD3D9Caps->MaxVertexIndex; \ - _pWineCaps->MaxStreams = &_pD3D9Caps->MaxStreams; \ - _pWineCaps->MaxStreamStride = &_pD3D9Caps->MaxStreamStride; \ - _pWineCaps->VertexShaderVersion = &_pD3D9Caps->VertexShaderVersion; \ - _pWineCaps->MaxVertexShaderConst = &_pD3D9Caps->MaxVertexShaderConst; \ - _pWineCaps->PixelShaderVersion = &_pD3D9Caps->PixelShaderVersion; \ - _pWineCaps->PixelShader1xMaxValue = &_pD3D9Caps->PixelShader1xMaxValue; \ - _pWineCaps->DevCaps2 = &_pD3D9Caps->DevCaps2; \ - _pWineCaps->MaxNpatchTessellationLevel = &_pD3D9Caps->MaxNpatchTessellationLevel; \ - _pWineCaps->MasterAdapterOrdinal = &_pD3D9Caps->MasterAdapterOrdinal; \ - _pWineCaps->AdapterOrdinalInGroup = &_pD3D9Caps->AdapterOrdinalInGroup; \ - _pWineCaps->NumberOfAdaptersInGroup = &_pD3D9Caps->NumberOfAdaptersInGroup; \ - _pWineCaps->DeclTypes = &_pD3D9Caps->DeclTypes; \ - _pWineCaps->NumSimultaneousRTs = &_pD3D9Caps->NumSimultaneousRTs; \ - _pWineCaps->StretchRectFilterCaps = &_pD3D9Caps->StretchRectFilterCaps; \ - _pWineCaps->VS20Caps.Caps = &_pD3D9Caps->VS20Caps.Caps; \ - _pWineCaps->VS20Caps.DynamicFlowControlDepth = &_pD3D9Caps->VS20Caps.DynamicFlowControlDepth; \ - _pWineCaps->VS20Caps.NumTemps = &_pD3D9Caps->VS20Caps.NumTemps; \ - _pWineCaps->VS20Caps.NumTemps = &_pD3D9Caps->VS20Caps.NumTemps; \ - _pWineCaps->VS20Caps.StaticFlowControlDepth = &_pD3D9Caps->VS20Caps.StaticFlowControlDepth; \ - _pWineCaps->PS20Caps.Caps = &_pD3D9Caps->PS20Caps.Caps; \ - _pWineCaps->PS20Caps.DynamicFlowControlDepth = &_pD3D9Caps->PS20Caps.DynamicFlowControlDepth; \ - _pWineCaps->PS20Caps.NumTemps = &_pD3D9Caps->PS20Caps.NumTemps; \ - _pWineCaps->PS20Caps.StaticFlowControlDepth = &_pD3D9Caps->PS20Caps.StaticFlowControlDepth; \ - _pWineCaps->PS20Caps.NumInstructionSlots = &_pD3D9Caps->PS20Caps.NumInstructionSlots; \ - _pWineCaps->VertexTextureFilterCaps = &_pD3D9Caps->VertexTextureFilterCaps; \ - _pWineCaps->MaxVShaderInstructionsExecuted = &_pD3D9Caps->MaxVShaderInstructionsExecuted; \ - _pWineCaps->MaxPShaderInstructionsExecuted = &_pD3D9Caps->MaxPShaderInstructionsExecuted; \ - _pWineCaps->MaxVertexShader30InstructionSlots = &_pD3D9Caps->MaxVertexShader30InstructionSlots; \ - _pWineCaps->MaxPixelShader30InstructionSlots = &_pD3D9Caps->MaxPixelShader30InstructionSlots; +#define WINECAPSTOD3D9CAPS(_pD3D9Caps, _pWineCaps) \ + _pD3D9Caps->DeviceType = (D3DDEVTYPE) _pWineCaps->DeviceType; \ + _pD3D9Caps->AdapterOrdinal = _pWineCaps->AdapterOrdinal; \ + _pD3D9Caps->Caps = _pWineCaps->Caps; \ + _pD3D9Caps->Caps2 = _pWineCaps->Caps2; \ + _pD3D9Caps->Caps3 = _pWineCaps->Caps3; \ + _pD3D9Caps->PresentationIntervals = _pWineCaps->PresentationIntervals; \ + _pD3D9Caps->CursorCaps = _pWineCaps->CursorCaps; \ + _pD3D9Caps->DevCaps = _pWineCaps->DevCaps; \ + _pD3D9Caps->PrimitiveMiscCaps = _pWineCaps->PrimitiveMiscCaps; \ + _pD3D9Caps->RasterCaps = _pWineCaps->RasterCaps; \ + _pD3D9Caps->ZCmpCaps = _pWineCaps->ZCmpCaps; \ + _pD3D9Caps->SrcBlendCaps = _pWineCaps->SrcBlendCaps; \ + _pD3D9Caps->DestBlendCaps = _pWineCaps->DestBlendCaps; \ + _pD3D9Caps->AlphaCmpCaps = _pWineCaps->AlphaCmpCaps; \ + _pD3D9Caps->ShadeCaps = _pWineCaps->ShadeCaps; \ + _pD3D9Caps->TextureCaps = _pWineCaps->TextureCaps; \ + _pD3D9Caps->TextureFilterCaps = _pWineCaps->TextureFilterCaps; \ + _pD3D9Caps->CubeTextureFilterCaps = _pWineCaps->CubeTextureFilterCaps; \ + _pD3D9Caps->VolumeTextureFilterCaps = _pWineCaps->VolumeTextureFilterCaps; \ + _pD3D9Caps->TextureAddressCaps = _pWineCaps->TextureAddressCaps; \ + _pD3D9Caps->VolumeTextureAddressCaps = _pWineCaps->VolumeTextureAddressCaps; \ + _pD3D9Caps->LineCaps = _pWineCaps->LineCaps; \ + _pD3D9Caps->MaxTextureWidth = _pWineCaps->MaxTextureWidth; \ + _pD3D9Caps->MaxTextureHeight = _pWineCaps->MaxTextureHeight; \ + _pD3D9Caps->MaxVolumeExtent = _pWineCaps->MaxVolumeExtent; \ + _pD3D9Caps->MaxTextureRepeat = _pWineCaps->MaxTextureRepeat; \ + _pD3D9Caps->MaxTextureAspectRatio = _pWineCaps->MaxTextureAspectRatio; \ + _pD3D9Caps->MaxAnisotropy = _pWineCaps->MaxAnisotropy; \ + _pD3D9Caps->MaxVertexW = _pWineCaps->MaxVertexW; \ + _pD3D9Caps->GuardBandLeft = _pWineCaps->GuardBandLeft; \ + _pD3D9Caps->GuardBandTop = _pWineCaps->GuardBandTop; \ + _pD3D9Caps->GuardBandRight = _pWineCaps->GuardBandRight; \ + _pD3D9Caps->GuardBandBottom = _pWineCaps->GuardBandBottom; \ + _pD3D9Caps->ExtentsAdjust = _pWineCaps->ExtentsAdjust; \ + _pD3D9Caps->StencilCaps = _pWineCaps->StencilCaps; \ + _pD3D9Caps->FVFCaps = _pWineCaps->FVFCaps; \ + _pD3D9Caps->TextureOpCaps = _pWineCaps->TextureOpCaps; \ + _pD3D9Caps->MaxTextureBlendStages = _pWineCaps->MaxTextureBlendStages; \ + _pD3D9Caps->MaxSimultaneousTextures = _pWineCaps->MaxSimultaneousTextures; \ + _pD3D9Caps->VertexProcessingCaps = _pWineCaps->VertexProcessingCaps; \ + _pD3D9Caps->MaxActiveLights = _pWineCaps->MaxActiveLights; \ + _pD3D9Caps->MaxUserClipPlanes = _pWineCaps->MaxUserClipPlanes; \ + _pD3D9Caps->MaxVertexBlendMatrices = _pWineCaps->MaxVertexBlendMatrices; \ + _pD3D9Caps->MaxVertexBlendMatrixIndex = _pWineCaps->MaxVertexBlendMatrixIndex; \ + _pD3D9Caps->MaxPointSize = _pWineCaps->MaxPointSize; \ + _pD3D9Caps->MaxPrimitiveCount = _pWineCaps->MaxPrimitiveCount; \ + _pD3D9Caps->MaxVertexIndex = _pWineCaps->MaxVertexIndex; \ + _pD3D9Caps->MaxStreams = _pWineCaps->MaxStreams; \ + _pD3D9Caps->MaxStreamStride = _pWineCaps->MaxStreamStride; \ + _pD3D9Caps->VertexShaderVersion = _pWineCaps->VertexShaderVersion; \ + _pD3D9Caps->MaxVertexShaderConst = _pWineCaps->MaxVertexShaderConst; \ + _pD3D9Caps->PixelShaderVersion = _pWineCaps->PixelShaderVersion; \ + _pD3D9Caps->PixelShader1xMaxValue = _pWineCaps->PixelShader1xMaxValue; \ + _pD3D9Caps->DevCaps2 = _pWineCaps->DevCaps2; \ + _pD3D9Caps->MaxNpatchTessellationLevel = _pWineCaps->MaxNpatchTessellationLevel; \ + _pD3D9Caps->MasterAdapterOrdinal = _pWineCaps->MasterAdapterOrdinal; \ + _pD3D9Caps->AdapterOrdinalInGroup = _pWineCaps->AdapterOrdinalInGroup; \ + _pD3D9Caps->NumberOfAdaptersInGroup = _pWineCaps->NumberOfAdaptersInGroup; \ + _pD3D9Caps->DeclTypes = _pWineCaps->DeclTypes; \ + _pD3D9Caps->NumSimultaneousRTs = _pWineCaps->NumSimultaneousRTs; \ + _pD3D9Caps->StretchRectFilterCaps = _pWineCaps->StretchRectFilterCaps; \ + _pD3D9Caps->VS20Caps.Caps = _pWineCaps->VS20Caps.Caps; \ + _pD3D9Caps->VS20Caps.DynamicFlowControlDepth = _pWineCaps->VS20Caps.DynamicFlowControlDepth; \ + _pD3D9Caps->VS20Caps.NumTemps = _pWineCaps->VS20Caps.NumTemps; \ + _pD3D9Caps->VS20Caps.NumTemps = _pWineCaps->VS20Caps.NumTemps; \ + _pD3D9Caps->VS20Caps.StaticFlowControlDepth = _pWineCaps->VS20Caps.StaticFlowControlDepth; \ + _pD3D9Caps->PS20Caps.Caps = _pWineCaps->PS20Caps.Caps; \ + _pD3D9Caps->PS20Caps.DynamicFlowControlDepth = _pWineCaps->PS20Caps.DynamicFlowControlDepth; \ + _pD3D9Caps->PS20Caps.NumTemps = _pWineCaps->PS20Caps.NumTemps; \ + _pD3D9Caps->PS20Caps.StaticFlowControlDepth = _pWineCaps->PS20Caps.StaticFlowControlDepth; \ + _pD3D9Caps->PS20Caps.NumInstructionSlots = _pWineCaps->PS20Caps.NumInstructionSlots; \ + _pD3D9Caps->VertexTextureFilterCaps = _pWineCaps->VertexTextureFilterCaps; \ + _pD3D9Caps->MaxVShaderInstructionsExecuted = _pWineCaps->MaxVShaderInstructionsExecuted; \ + _pD3D9Caps->MaxPShaderInstructionsExecuted = _pWineCaps->MaxPShaderInstructionsExecuted; \ + _pD3D9Caps->MaxVertexShader30InstructionSlots = _pWineCaps->MaxVertexShader30InstructionSlots; \ + _pD3D9Caps->MaxPixelShader30InstructionSlots = _pWineCaps->MaxPixelShader30InstructionSlots; /* =========================================================================== - D3D9 interfactes + D3D9 interfaces =========================================================================== */ /* ---------- */ @@ -139,7 +139,7 @@ extern CRITICAL_SECTION d3d9_cs; /***************************************************************************** * Predeclare the interface implementation structures */ -extern const IDirect3D9Vtbl Direct3D9_Vtbl; +extern const IDirect3D9ExVtbl Direct3D9_Vtbl; /***************************************************************************** * IDirect3D implementation structure @@ -147,12 +147,14 @@ extern const IDirect3D9Vtbl Direct3D9_Vtbl; typedef struct IDirect3D9Impl { /* IUnknown fields */ - const IDirect3D9Vtbl *lpVtbl; + const IDirect3D9ExVtbl *lpVtbl; LONG ref; /* The WineD3D device */ IWineD3D *WineD3D; + /* Created via Direct3DCreate9Ex? Can QI extended interfaces */ + BOOL extended; } IDirect3D9Impl; void filter_caps(D3DCAPS9* pCaps); @@ -164,7 +166,7 @@ void filter_caps(D3DCAPS9* pCaps); /***************************************************************************** * Predeclare the interface implementation structures */ -extern const IDirect3DDevice9Vtbl Direct3DDevice9_Vtbl; +extern const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl; /***************************************************************************** * IDirect3DDevice9 implementation structure @@ -172,7 +174,7 @@ extern const IDirect3DDevice9Vtbl Direct3DDevice9_Vtbl; typedef struct IDirect3DDevice9Impl { /* IUnknown fields */ - const IDirect3DDevice9Vtbl *lpVtbl; + const IDirect3DDevice9ExVtbl *lpVtbl; LONG ref; /* IDirect3DDevice9 fields */ @@ -184,48 +186,49 @@ typedef struct IDirect3DDevice9Impl IDirect3DVertexDeclaration9 **convertedDecls; unsigned int numConvertedDecls, declArraySize; + BOOL notreset; } IDirect3DDevice9Impl; /* IDirect3DDevice9: */ -extern HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9 iface, IDirect3D9** ppD3D9); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, IDirect3DSwapChain9** pSwapChain); -extern UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9 iface); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9 iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9 iface, UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9 iface, D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB); -extern HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9 iface); -extern HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9 iface, IDirect3DStateBlock9** ppSB); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9* pDecl); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9** ppDecl); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9 iface, DWORD* pFVF); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9 iface, CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9 iface, IDirect3DVertexShader9* pShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9 iface, IDirect3DVertexShader9** ppShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT StartRegister, float* pConstantData, UINT Vector4fCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT StartRegister, int* pConstantData, UINT Vector4iCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT StartRegister, BOOL* pConstantData, UINT BoolCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9 iface, CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9* pShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9** ppShader); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT StartRegister, float* pConstantData, UINT Vector4fCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT StartRegister, int* pConstantData, UINT Vector4iCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT StartRegister, BOOL* pConstantData, UINT BoolCount); -extern HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9 iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9EX iface, IDirect3D9** ppD3D9); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE9EX iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, IDirect3DSwapChain9** pSwapChain); +extern UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9EX iface); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9EX iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9EX iface, UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9EX iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9EX iface, D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB); +extern HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9EX iface); +extern HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9EX iface, IDirect3DStateBlock9** ppSB); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9EX iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexDeclaration9* pDecl); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexDeclaration9** ppDecl); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9EX iface, DWORD FVF); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9EX iface, DWORD* pFVF); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9EX iface, CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexShader9* pShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexShader9** ppShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, float* pConstantData, UINT Vector4fCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, int* pConstantData, UINT Vector4iCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, BOOL* pConstantData, UINT BoolCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9EX iface, CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9EX iface, IDirect3DPixelShader9* pShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9EX iface, IDirect3DPixelShader9** ppShader); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, float* pConstantData, UINT Vector4fCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, int* pConstantData, UINT Vector4iCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT StartRegister, BOOL* pConstantData, UINT BoolCount); +extern HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9EX iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery); /* ---------------- */ @@ -268,7 +271,7 @@ typedef struct IDirect3DSwapChain9Impl IWineD3DSwapChain *wineD3DSwapChain; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; /* Flags an implicit swap chain */ BOOL isImplicit; @@ -316,7 +319,7 @@ typedef struct IDirect3DSurface9Impl IWineD3DSurface *wineD3DSurface; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; /* The surface container */ IUnknown *container; @@ -345,7 +348,7 @@ typedef struct IDirect3DVertexBuffer9Impl IWineD3DVertexBuffer *wineD3DVertexBuffer; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DVertexBuffer9Impl; /* --------------------- */ @@ -365,7 +368,7 @@ typedef struct IDirect3DIndexBuffer9Impl IWineD3DIndexBuffer *wineD3DIndexBuffer; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DIndexBuffer9Impl; /* --------------------- */ @@ -405,7 +408,7 @@ typedef struct IDirect3DCubeTexture9Impl IWineD3DCubeTexture *wineD3DCubeTexture; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DCubeTexture9Impl; @@ -426,7 +429,7 @@ typedef struct IDirect3DTexture9Impl IWineD3DTexture *wineD3DTexture; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DTexture9Impl; /* ----------------------- */ @@ -446,7 +449,7 @@ typedef struct IDirect3DVolumeTexture9Impl IWineD3DVolumeTexture *wineD3DVolumeTexture; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DVolumeTexture9Impl; /* ----------------------- */ @@ -465,7 +468,7 @@ typedef struct IDirect3DStateBlock9Impl { IWineD3DStateBlock *wineD3DStateBlock; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DStateBlock9Impl; @@ -482,14 +485,14 @@ typedef struct IDirect3DVertexDeclaration9Impl { LONG ref; D3DVERTEXELEMENT9 *elements; - size_t element_count; + UINT element_count; /* IDirect3DVertexDeclaration9 fields */ IWineD3DVertexDeclaration *wineD3DVertexDeclaration; DWORD convFVF; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DVertexDeclaration9Impl; void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface); @@ -510,7 +513,7 @@ typedef struct IDirect3DVertexShader9Impl { IWineD3DVertexShader *wineD3DVertexShader; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DVertexShader9Impl; /* --------------------- */ @@ -529,7 +532,7 @@ typedef struct IDirect3DPixelShader9Impl { IWineD3DPixelShader *wineD3DPixelShader; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DPixelShader9Impl; /* --------------- */ @@ -548,7 +551,7 @@ typedef struct IDirect3DQuery9Impl { IWineD3DQuery *wineD3DQuery; /* Parent reference */ - LPDIRECT3DDEVICE9 parentDevice; + LPDIRECT3DDEVICE9EX parentDevice; } IDirect3DQuery9Impl; diff --git a/reactos/dll/directx/wine/d3d9/device.c b/reactos/dll/directx/wine/d3d9/device.c index f4024a21325..8aab2307819 100644 --- a/reactos/dll/directx/wine/d3d9/device.c +++ b/reactos/dll/directx/wine/d3d9/device.c @@ -27,14 +27,36 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d9); /* IDirect3D IUnknown parts follow: */ -static HRESULT WINAPI IDirect3DDevice9Impl_QueryInterface(LPDIRECT3DDEVICE9 iface, REFIID riid, LPVOID* ppobj) { +static HRESULT WINAPI IDirect3DDevice9Impl_QueryInterface(LPDIRECT3DDEVICE9EX iface, REFIID riid, LPVOID* ppobj) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IDirect3D9 *d3d; + IDirect3D9Impl *d3dimpl; if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirect3DDevice9)) { IUnknown_AddRef(iface); *ppobj = This; + TRACE("Returning IDirect3DDevice9 interface at %p\n", *ppobj); return S_OK; + } else if(IsEqualGUID(riid, &IID_IDirect3DDevice9Ex)) { + /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex. + * It doesn't matter with which function the device was created. + */ + IDirect3DDevice9_GetDirect3D(iface, &d3d); + d3dimpl = (IDirect3D9Impl *) d3d; + + if(d3dimpl->extended) { + *ppobj = iface; + IDirect3DDevice9Ex_AddRef((IDirect3DDevice9Ex *) *ppobj); + IDirect3D9_Release(d3d); + TRACE("Returning IDirect3DDevice9Ex interface at %p\n", *ppobj); + return S_OK; + } else { + WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE\n"); + IDirect3D9_Release(d3d); + *ppobj = NULL; + return E_NOINTERFACE; + } } WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj); @@ -42,7 +64,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_QueryInterface(LPDIRECT3DDEVICE9 ifac return E_NOINTERFACE; } -static ULONG WINAPI IDirect3DDevice9Impl_AddRef(LPDIRECT3DDEVICE9 iface) { +static ULONG WINAPI IDirect3DDevice9Impl_AddRef(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; ULONG ref = InterlockedIncrement(&This->ref); @@ -51,7 +73,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_AddRef(LPDIRECT3DDEVICE9 iface) { return ref; } -static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { +static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; ULONG ref; @@ -61,7 +83,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - int i; + unsigned i; This->inDestruction = TRUE; EnterCriticalSection(&d3d9_cs); @@ -82,18 +104,23 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { } /* IDirect3DDevice Interface follow: */ -static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(LPDIRECT3DDEVICE9 iface) { +static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; - TRACE("(%p) : Relay\n", This); + TRACE("(%p)\n", This); EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice); LeaveCriticalSection(&d3d9_cs); + if(hr == WINED3D_OK && This->notreset) { + TRACE("D3D9 Device is marked not reset\n"); + hr = D3DERR_DEVICENOTRESET; + } + return hr; } -static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE9 iface) { +static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -104,7 +131,7 @@ static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDE return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(LPDIRECT3DDEVICE9 iface) { +static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); @@ -115,7 +142,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(LPDIRECT3DDEV return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9 iface, IDirect3D9** ppD3D9) { +HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9EX iface, IDirect3D9** ppD3D9) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr = D3D_OK; IWineD3D* pWineD3D; @@ -141,7 +168,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9 iface, IDire return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9 iface, D3DCAPS9* pCaps) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9EX iface, D3DCAPS9* pCaps) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; WINED3DCAPS *pWineCaps; @@ -156,10 +183,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9 ifa } memset(pCaps, 0, sizeof(*pCaps)); - D3D9CAPSTOWINECAPS(pCaps, pWineCaps) EnterCriticalSection(&d3d9_cs); hrc = IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pWineCaps); LeaveCriticalSection(&d3d9_cs); + WINECAPSTOD3D9CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */ @@ -171,7 +198,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9 ifa return hrc; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -182,7 +209,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(LPDIRECT3DDEVICE9 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(LPDIRECT3DDEVICE9EX iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -193,7 +220,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(LPDIRECT3DDEV return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVICE9 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVICE9EX iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *pSurface = (IDirect3DSurface9Impl*)pCursorBitmap; HRESULT hr; @@ -205,12 +232,12 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVIC } EnterCriticalSection(&d3d9_cs); - hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice, XHotSpot, YHotSpot, (IWineD3DSurface*)pSurface->wineD3DSurface); + hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice, XHotSpot, YHotSpot, pSurface->wineD3DSurface); LeaveCriticalSection(&d3d9_cs); return hr; } -static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9 iface, int XScreenSpace, int YScreenSpace, DWORD Flags) { +static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9EX iface, int XScreenSpace, int YScreenSpace, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); @@ -219,7 +246,7 @@ static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9 LeaveCriticalSection(&d3d9_cs); } -static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9 iface, BOOL bShow) { +static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9EX iface, BOOL bShow) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; BOOL ret; TRACE("(%p) Relay\n", This); @@ -230,13 +257,111 @@ static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9 iface, return ret; } -static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) { +static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data) { + BOOL *resources_ok = (BOOL *) data; + WINED3DRESOURCETYPE type; + HRESULT ret = S_OK; + WINED3DSURFACE_DESC surface_desc; + WINED3DVOLUME_DESC volume_desc; + WINED3DINDEXBUFFER_DESC index_desc; + WINED3DVERTEXBUFFER_DESC vertex_desc; + WINED3DFORMAT dummy_format; + DWORD dummy_dword; + WINED3DPOOL pool = WINED3DPOOL_SCRATCH; /* a harmless pool */ + IUnknown *parent; + + type = IWineD3DResource_GetType(resource); + switch(type) { + case WINED3DRTYPE_SURFACE: + surface_desc.Format = &dummy_format; + surface_desc.Type = &type; + surface_desc.Usage = &dummy_dword; + surface_desc.Pool = &pool; + surface_desc.Size = &dummy_dword; + surface_desc.MultiSampleType = &dummy_dword; + surface_desc.MultiSampleQuality = &dummy_dword; + surface_desc.Width = &dummy_dword; + surface_desc.Height = &dummy_dword; + + IWineD3DSurface_GetDesc((IWineD3DSurface *) resource, &surface_desc); + break; + + case WINED3DRTYPE_VOLUME: + volume_desc.Format = &dummy_format; + volume_desc.Type = &type; + volume_desc.Usage = &dummy_dword; + volume_desc.Pool = &pool; + volume_desc.Size = &dummy_dword; + volume_desc.Width = &dummy_dword; + volume_desc.Height = &dummy_dword; + volume_desc.Depth = &dummy_dword; + IWineD3DVolume_GetDesc((IWineD3DVolume *) resource, &volume_desc); + break; + + case WINED3DRTYPE_INDEXBUFFER: + IWineD3DIndexBuffer_GetDesc((IWineD3DIndexBuffer *) resource, &index_desc); + pool = index_desc.Pool; + break; + + case WINED3DRTYPE_VERTEXBUFFER: + IWineD3DVertexBuffer_GetDesc((IWineD3DVertexBuffer *) resource, &vertex_desc); + pool = vertex_desc.Pool; + break; + + /* No need to check for textures. If there is a D3DPOOL_DEFAULT texture, there + * is a D3DPOOL_DEFAULT surface or volume as well + */ + default: + break; + } + + if(pool == WINED3DPOOL_DEFAULT) { + IWineD3DResource_GetParent(resource, &parent); + if(IUnknown_Release(parent) == 0) { + TRACE("Parent %p is an implicit resource with ref 0\n", parent); + } else { + WARN("Resource %p(wineD3D %p) with pool D3DPOOL_DEFAULT blocks the Reset call\n", parent, resource); + ret = S_FALSE; + *resources_ok = FALSE; + } + } + IWineD3DResource_Release(resource); + + return ret; +} + +static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9EX iface, D3DPRESENT_PARAMETERS* pPresentationParameters) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; WINED3DPRESENT_PARAMETERS localParameters; HRESULT hr; + BOOL resources_ok = TRUE; + UINT i; TRACE("(%p) Relay pPresentationParameters(%p)\n", This, pPresentationParameters); + /* Reset states that hold a COM object. WineD3D holds an internal reference to set objects, because + * such objects can still be used for rendering after their external d3d9 object has been destroyed. + * These objects must not be enumerated. Unsetting them tells WineD3D that the application will not + * make use of the hidden reference and destroys the objects. + * + * Unsetting them is no problem, because the states are supposed to be reset anyway. If the validation + * below fails, the device is considered "lost", and _Reset and _Release are the only allowed calls + */ + IWineD3DDevice_SetIndices(This->WineD3DDevice, NULL); + for(i = 0; i < 16; i++) { + IWineD3DDevice_SetStreamSource(This->WineD3DDevice, i, NULL, 0, 0); + } + for(i = 0; i < 16; i++) { + IWineD3DDevice_SetTexture(This->WineD3DDevice, i, NULL); + } + + IWineD3DDevice_EnumResources(This->WineD3DDevice, reset_enum_callback, &resources_ok); + if(!resources_ok) { + WARN("The application is holding D3DPOOL_DEFAULT resources, rejecting reset\n"); + This->notreset = TRUE; + return WINED3DERR_INVALIDCALL; + } + localParameters.BackBufferWidth = pPresentationParameters->BackBufferWidth; localParameters.BackBufferHeight = pPresentationParameters->BackBufferHeight; localParameters.BackBufferFormat = pPresentationParameters->BackBufferFormat; @@ -255,26 +380,31 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DP EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_Reset(This->WineD3DDevice, &localParameters); LeaveCriticalSection(&d3d9_cs); + if(FAILED(hr)) { + This->notreset = TRUE; - pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; - pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; - pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; - pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; - pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; - pPresentationParameters->MultiSampleQuality = localParameters.MultiSampleQuality; - pPresentationParameters->SwapEffect = localParameters.SwapEffect; - pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; - pPresentationParameters->Windowed = localParameters.Windowed; - pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; - pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; - pPresentationParameters->Flags = localParameters.Flags; - pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; - pPresentationParameters->PresentationInterval = localParameters.PresentationInterval; + pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; + pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; + pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; + pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; + pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; + pPresentationParameters->MultiSampleQuality = localParameters.MultiSampleQuality; + pPresentationParameters->SwapEffect = localParameters.SwapEffect; + pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; + pPresentationParameters->Windowed = localParameters.Windowed; + pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; + pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; + pPresentationParameters->Flags = localParameters.Flags; + pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; + pPresentationParameters->PresentationInterval = localParameters.PresentationInterval; + } else { + This->notreset = FALSE; + } return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* +static HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9EX iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; @@ -286,7 +416,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9 iface, CO return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 ** ppBackBuffer) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 ** ppBackBuffer) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DSurface *retSurface = NULL; HRESULT rc = D3D_OK; @@ -294,7 +424,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 ifa TRACE("(%p) Relay\n", This); EnterCriticalSection(&d3d9_cs); - rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, iSwapChain, BackBuffer, (WINED3DBACKBUFFER_TYPE) Type, (IWineD3DSurface **)&retSurface); + rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, iSwapChain, BackBuffer, (WINED3DBACKBUFFER_TYPE) Type, &retSurface); if (rc == D3D_OK && NULL != retSurface && NULL != ppBackBuffer) { IWineD3DSurface_GetParent(retSurface, (IUnknown **)ppBackBuffer); IWineD3DSurface_Release(retSurface); @@ -302,7 +432,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 ifa LeaveCriticalSection(&d3d9_cs); return rc; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -313,7 +443,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9 i return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(LPDIRECT3DDEVICE9 iface, BOOL bEnableDialogs) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(LPDIRECT3DDEVICE9EX iface, BOOL bEnableDialogs) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -324,7 +454,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(LPDIRECT3DDEVICE9 if return hr; } -static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) { +static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); @@ -335,7 +465,7 @@ static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(LPDIRECT3DDEVICE9 iface, UI LeaveCriticalSection(&d3d9_cs); } -static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { +static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); @@ -346,16 +476,11 @@ static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9 iface, UI } -static HRESULT WINAPI IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface9 **ppSurface,D3DRESOURCETYPE Type, UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,HANDLE* pSharedHandle ) { +static HRESULT WINAPI IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface9 **ppSurface,D3DRESOURCETYPE Type, UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,HANDLE* pSharedHandle ) { HRESULT hrc; IDirect3DSurface9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); - if(MultisampleQuality < 0) { - FIXME("MultisampleQuality out of range %d, substituting 0\n", MultisampleQuality); - /*FIXME: Find out what windows does with a MultisampleQuality < 0 */ - MultisampleQuality=0; - } if(MultisampleQuality > 0){ FIXME("MultisampleQuality set to %d, bstituting 0\n", MultisampleQuality); @@ -398,7 +523,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9 ifac -static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, +static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { @@ -412,7 +537,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, +static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { @@ -428,7 +553,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3 } -static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) { +static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -439,7 +564,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(LPDIRECT3DDEVICE9 ifa return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(LPDIRECT3DDEVICE9 iface, IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) { +static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(LPDIRECT3DDEVICE9EX iface, IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -451,14 +576,14 @@ static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(LPDIRECT3DDEVICE9 ifa } /* This isn't in MSDN! -static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBuffer(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pDestSurface) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBuffer(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; FIXME("(%p) : stub\n", This); return D3D_OK; } */ -static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *renderTarget = (IDirect3DSurface9Impl *)pRenderTarget; IDirect3DSurface9Impl *destSurface = (IDirect3DSurface9Impl *)pDestSurface; @@ -471,7 +596,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(LPDIRECT3DDEVIC return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, IDirect3DSurface9* pDestSurface) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *destSurface = (IDirect3DSurface9Impl *)pDestSurface; HRESULT hr; @@ -483,7 +608,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(LPDIRECT3DDEVICE return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) { +static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *src = (IDirect3DSurface9Impl *) pSourceSurface; IDirect3DSurface9Impl *dst = (IDirect3DSurface9Impl *) pDestSurface; @@ -496,12 +621,31 @@ static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) { +static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *surface = (IDirect3DSurface9Impl *)pSurface; + WINED3DPOOL pool; + WINED3DRESOURCETYPE restype; + DWORD usage; + WINED3DSURFACE_DESC desc; HRESULT hr; TRACE("(%p) Relay\n" , This); + memset(&desc, 0, sizeof(desc)); + desc.Usage = &usage; + desc.Pool = &pool; + desc.Type = &restype; + IWineD3DSurface_GetDesc(surface->wineD3DSurface, &desc); + + /* This method is only allowed with surfaces that are render targets, or offscreen plain surfaces + * in D3DPOOL_DEFAULT + */ + if(!(usage & WINED3DUSAGE_RENDERTARGET) && (pool != D3DPOOL_DEFAULT || restype != D3DRTYPE_SURFACE)) { + WARN("Surface is not a render target, or not a stand-alone D3DPOOL_DEFAULT surface\n"); + return D3DERR_INVALIDCALL; + } + + /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */ /* Note: D3DRECT is compatible with WINED3DRECT */ EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_ColorFill(This->WineD3DDevice, surface->wineD3DSurface, (CONST WINED3DRECT*)pRect, color); @@ -509,15 +653,14 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9 iface, return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { +static HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { HRESULT hr; TRACE("Relay\n"); if(Pool == D3DPOOL_MANAGED ){ FIXME("Attempting to create a managed offscreen plain surface\n"); return D3DERR_INVALIDCALL; } - /*MSDN: D3DPOOL_SCRATCH will return a surface that has identical characteristics to a surface created by the Microsoft DirectX 8.x method CreateImageSurface. - + /* 'Off-screen plain surfaces are always lockable, regardless of their pool types.' but then... D3DPOOL_DEFAULT is the appropriate pool for use with the IDirect3DDevice9::StretchRect and IDirect3DDevice9::ColorFill. @@ -531,19 +674,19 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIREC } /* TODO: move to wineD3D */ -static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9EX iface, DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *pSurface = (IDirect3DSurface9Impl*)pRenderTarget; HRESULT hr; TRACE("(%p) Relay\n" , This); EnterCriticalSection(&d3d9_cs); - hr = IWineD3DDevice_SetRenderTarget(This->WineD3DDevice, RenderTargetIndex, pSurface ? (IWineD3DSurface*)pSurface->wineD3DSurface : NULL); + hr = IWineD3DDevice_SetRenderTarget(This->WineD3DDevice, RenderTargetIndex, pSurface ? pSurface->wineD3DSurface : NULL); LeaveCriticalSection(&d3d9_cs); return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9EX iface, DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr = D3D_OK; IWineD3DSurface *pRenderTarget; @@ -569,7 +712,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 i return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pZStencilSurface) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9* pZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSurface9Impl *pSurface; HRESULT hr; @@ -582,7 +725,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDE return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9 **ppZStencilSurface) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9 **ppZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr = D3D_OK; IWineD3DSurface *pZStencilSurface; @@ -594,22 +737,19 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDE EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice,&pZStencilSurface); - if(hr == D3D_OK) { - if(pZStencilSurface != NULL){ - IWineD3DSurface_GetParent(pZStencilSurface,(IUnknown**)ppZStencilSurface); - IWineD3DSurface_Release(pZStencilSurface); - } else { - *ppZStencilSurface = NULL; - } + if (hr == WINED3D_OK) { + IWineD3DSurface_GetParent(pZStencilSurface,(IUnknown**)ppZStencilSurface); + IWineD3DSurface_Release(pZStencilSurface); } else { - WARN("Call to IWineD3DDevice_GetDepthStencilSurface failed\n"); + if (hr != WINED3DERR_NOTFOUND) + WARN("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr); *ppZStencilSurface = NULL; } LeaveCriticalSection(&d3d9_cs); return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9 iface) { +static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -620,7 +760,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9 iface) return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9 iface) { +static HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -631,7 +771,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9 iface) { return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { +static HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9EX iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -643,7 +783,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9 iface, DWOR return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* lpMatrix) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9EX iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* lpMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -655,7 +795,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9 ifac return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9EX iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n" , This); @@ -663,7 +803,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9 ifac return IWineD3DDevice_GetTransform(This->WineD3DDevice, State, (WINED3DMATRIX*) pMatrix); } -static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) { +static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9EX iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -675,7 +815,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9 return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(LPDIRECT3DDEVICE9 iface, CONST D3DVIEWPORT9* pViewport) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(LPDIRECT3DDEVICE9EX iface, CONST D3DVIEWPORT9* pViewport) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -687,7 +827,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(LPDIRECT3DDEVICE9 iface, D3DVIEWPORT9* pViewport) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(LPDIRECT3DDEVICE9EX iface, D3DVIEWPORT9* pViewport) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -699,7 +839,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(LPDIRECT3DDEVICE9 iface, CONST D3DMATERIAL9* pMaterial) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(LPDIRECT3DDEVICE9EX iface, CONST D3DMATERIAL9* pMaterial) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -711,7 +851,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(LPDIRECT3DDEVICE9 iface, D3DMATERIAL9* pMaterial) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(LPDIRECT3DDEVICE9EX iface, D3DMATERIAL9* pMaterial) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -723,7 +863,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(LPDIRECT3DDEVICE9 iface, DWORD Index, CONST D3DLIGHT9* pLight) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(LPDIRECT3DDEVICE9EX iface, DWORD Index, CONST D3DLIGHT9* pLight) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -735,7 +875,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(LPDIRECT3DDEVICE9 iface, D return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(LPDIRECT3DDEVICE9 iface, DWORD Index, D3DLIGHT9* pLight) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(LPDIRECT3DDEVICE9EX iface, DWORD Index, D3DLIGHT9* pLight) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -747,7 +887,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(LPDIRECT3DDEVICE9 iface, D return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(LPDIRECT3DDEVICE9 iface, DWORD Index, BOOL Enable) { +static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(LPDIRECT3DDEVICE9EX iface, DWORD Index, BOOL Enable) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -758,7 +898,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(LPDIRECT3DDEVICE9 iface, DWORD Index, BOOL* pEnable) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(LPDIRECT3DDEVICE9EX iface, DWORD Index, BOOL* pEnable) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -769,7 +909,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(LPDIRECT3DDEVICE9 iface, DWORD Index, CONST float* pPlane) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(LPDIRECT3DDEVICE9EX iface, DWORD Index, CONST float* pPlane) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -780,7 +920,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(LPDIRECT3DDEVICE9 ifac return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(LPDIRECT3DDEVICE9 iface, DWORD Index, float* pPlane) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(LPDIRECT3DDEVICE9EX iface, DWORD Index, float* pPlane) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -791,7 +931,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(LPDIRECT3DDEVICE9 ifac return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD Value) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9EX iface, D3DRENDERSTATETYPE State, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -802,7 +942,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD* pValue) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9EX iface, D3DRENDERSTATETYPE State, DWORD* pValue) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -813,7 +953,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9 iface, CONST D3DCLIPSTATUS9* pClipStatus) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9EX iface, CONST D3DCLIPSTATUS9* pClipStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -824,7 +964,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9 ifa return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(LPDIRECT3DDEVICE9 iface, D3DCLIPSTATUS9* pClipStatus) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(LPDIRECT3DDEVICE9EX iface, D3DCLIPSTATUS9* pClipStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -835,7 +975,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(LPDIRECT3DDEVICE9 ifa return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9 **ppTexture) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9EX iface, DWORD Stage, IDirect3DBaseTexture9 **ppTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DBaseTexture *retTexture = NULL; HRESULT rc = D3D_OK; @@ -847,7 +987,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, } EnterCriticalSection(&d3d9_cs); - rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, (IWineD3DBaseTexture **)&retTexture); + rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, &retTexture); if (rc == D3D_OK && NULL != retTexture) { IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); IWineD3DBaseTexture_Release(retTexture); @@ -860,7 +1000,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, return rc; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9* pTexture) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9EX iface, DWORD Stage, IDirect3DBaseTexture9* pTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay %d %p\n" , This, Stage, pTexture); @@ -872,7 +1012,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9 iface, return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -883,7 +1023,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVI return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -894,7 +1034,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVI return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9 iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9EX iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -905,7 +1045,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9 i return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetSamplerState(LPDIRECT3DDEVICE9 iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetSamplerState(LPDIRECT3DDEVICE9EX iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -916,7 +1056,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetSamplerState(LPDIRECT3DDEVICE9 i return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(LPDIRECT3DDEVICE9 iface, DWORD* pNumPasses) { +static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(LPDIRECT3DDEVICE9EX iface, DWORD* pNumPasses) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -927,7 +1067,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(LPDIRECT3DDEVICE9EX iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -938,7 +1078,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(LPDIRECT3DDEVICE9 return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(LPDIRECT3DDEVICE9EX iface, UINT PaletteNumber, PALETTEENTRY* pEntries) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -949,7 +1089,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(LPDIRECT3DDEVICE9 return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE9EX iface, UINT PaletteNumber) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -960,7 +1100,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(LPDIRECT3D return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE9 iface, UINT* PaletteNumber) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE9EX iface, UINT* PaletteNumber) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -971,7 +1111,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(LPDIRECT3D return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(LPDIRECT3DDEVICE9 iface, CONST RECT* pRect) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(LPDIRECT3DDEVICE9EX iface, CONST RECT* pRect) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -982,7 +1122,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(LPDIRECT3DDEVICE9 iface, RECT* pRect) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(LPDIRECT3DDEVICE9EX iface, RECT* pRect) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -993,7 +1133,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(LPDIRECT3DDEVICE9 if return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIRECT3DDEVICE9 iface, BOOL bSoftware) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIRECT3DDEVICE9EX iface, BOOL bSoftware) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1004,18 +1144,18 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIREC return hr; } -static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(LPDIRECT3DDEVICE9 iface) { +static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hr; + BOOL ret; TRACE("(%p) Relay\n" , This); EnterCriticalSection(&d3d9_cs); - hr = IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); + ret = IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); LeaveCriticalSection(&d3d9_cs); - return hr; + return ret; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9 iface, float nSegments) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9EX iface, float nSegments) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1026,18 +1166,18 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9 ifa return hr; } -static float WINAPI IDirect3DDevice9Impl_GetNPatchMode(LPDIRECT3DDEVICE9 iface) { +static float WINAPI IDirect3DDevice9Impl_GetNPatchMode(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hr; + float ret; TRACE("(%p) Relay\n" , This); EnterCriticalSection(&d3d9_cs); - hr = IWineD3DDevice_GetNPatchMode(This->WineD3DDevice); + ret = IWineD3DDevice_GetNPatchMode(This->WineD3DDevice); LeaveCriticalSection(&d3d9_cs); - return hr; + return ret; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { +static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1048,7 +1188,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(LPDIRECT3DDEVICE9 iface return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, +static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; @@ -1062,7 +1202,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(LPDIRECT3DDEVI return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { +static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1073,7 +1213,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE9 i return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, +static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; @@ -1087,7 +1227,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDE return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9 iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) { +static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9EX iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DVertexDeclaration9Impl *Decl = (IDirect3DVertexDeclaration9Impl *) pVertexDecl; HRESULT hr; @@ -1127,7 +1267,7 @@ IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD hr = vdecl_convert_fvf(fvf, &elements); if (hr != S_OK) return NULL; - hr = IDirect3DDevice9Impl_CreateVertexDeclaration((IDirect3DDevice9 *) This, elements, &pDecl); + hr = IDirect3DDevice9Impl_CreateVertexDeclaration((IDirect3DDevice9Ex *) This, elements, &pDecl); HeapFree(GetProcessHeap(), 0, elements); /* CreateVertexDeclaration makes a copy */ if (hr != S_OK) return NULL; @@ -1156,14 +1296,13 @@ IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD return pDecl; } -HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF) { +HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9EX iface, DWORD FVF) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); EnterCriticalSection(&d3d9_cs); if (0 != FVF) { - HRESULT hr; IDirect3DVertexDeclaration9* pDecl = getConvertedDecl(This, FVF); if(!pDecl) { @@ -1185,7 +1324,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF) return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9 iface, DWORD* pFVF) { +HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9EX iface, DWORD* pFVF) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1196,7 +1335,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9 iface, DWORD* pFV return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) { +HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1209,7 +1348,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9 iface, U return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9 **pStream, UINT* OffsetInBytes, UINT* pStride) { +HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, IDirect3DVertexBuffer9 **pStream, UINT* OffsetInBytes, UINT* pStride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DVertexBuffer *retStream = NULL; HRESULT rc = D3D_OK; @@ -1221,7 +1360,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, U } EnterCriticalSection(&d3d9_cs); - rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, (IWineD3DVertexBuffer **)&retStream, OffsetInBytes, pStride); + rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, &retStream, OffsetInBytes, pStride); if (rc == D3D_OK && NULL != retStream) { IWineD3DVertexBuffer_GetParent(retStream, (IUnknown **)pStream); IWineD3DVertexBuffer_Release(retStream); @@ -1236,7 +1375,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, U return rc; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, UINT Divider) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, UINT Divider) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1247,7 +1386,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(LPDIRECT3DDEVIC return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, UINT* Divider) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, UINT* Divider) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -1258,7 +1397,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(LPDIRECT3DDEVIC return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(LPDIRECT3DDEVICE9 iface, IDirect3DIndexBuffer9* pIndexData) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(LPDIRECT3DDEVICE9EX iface, IDirect3DIndexBuffer9* pIndexData) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -1270,7 +1409,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(LPDIRECT3DDEVICE9 iface, return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9 iface, IDirect3DIndexBuffer9 **ppIndexData) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9EX iface, IDirect3DIndexBuffer9 **ppIndexData) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DIndexBuffer *retIndexData = NULL; HRESULT rc = D3D_OK; @@ -1294,7 +1433,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9 iface, return rc; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9 iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) { +static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9EX iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -1304,8 +1443,8 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9 ifa LeaveCriticalSection(&d3d9_cs); return hr; } -/*http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp*/ -static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9 iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) { + +static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9EX iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -1316,7 +1455,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9 ifac return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(LPDIRECT3DDEVICE9 iface, UINT Handle) { +static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(LPDIRECT3DDEVICE9EX iface, UINT Handle) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -1327,7 +1466,98 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(LPDIRECT3DDEVICE9 iface return hr; } -const IDirect3DDevice9Vtbl Direct3DDevice9_Vtbl = +static HRESULT WINAPI IDirect3DDevice9ExImpl_SetConvolutionMonoKernel(LPDIRECT3DDEVICE9EX iface, UINT width, UINT height, float *rows, float *columns) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d, %d, %p, %p) Stub!\n", This, width, height, rows, columns); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_ComposeRects(LPDIRECT3DDEVICE9EX iface, IDirect3DSurface9 *pSrc, IDirect3DDevice9 *pDst, IDirect3DVertexBuffer9 *pSrcRectDescs, UINT NumRects, IDirect3DVertexBuffer9 *pDstRectDescs, D3DCOMPOSERECTSOP Operation, int Xoffset, int Yoffset) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p, %p, %p, %d, %p, %d, %d, %d) Stub!\n", This, pSrc, pDst, pSrcRectDescs, NumRects, pDstRectDescs, Operation, Xoffset, Yoffset); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_PresentEx(LPDIRECT3DDEVICE9EX iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p= -> (%p), %p, %p, %p, 0x%08x) Stub!\n", This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_GetGPUThreadPriority(LPDIRECT3DDEVICE9EX iface, INT *pPriority) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p) Stub!\n", This, pPriority); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_SetGPUThreadPriority(LPDIRECT3DDEVICE9EX iface, INT Priority) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d) Stub!\n", This, Priority); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_WaitForVBlank(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d) Stub!\n", This, iSwapChain); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckresourceResidency(LPDIRECT3DDEVICE9EX iface, IDirect3DResource9 ** pResourceArray, UINT32 Numresources) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p, %d) Stub!\n", This, pResourceArray, Numresources); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_SetMaximumFrameLatency(LPDIRECT3DDEVICE9EX iface, UINT MaxLatency) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d) Stub!\n", This, MaxLatency); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_GetMaximumFrameLatency(LPDIRECT3DDEVICE9EX iface, UINT *pMaxLatency) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p) Stub!\n", This, pMaxLatency); + *pMaxLatency = 2; + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckdeviceState(LPDIRECT3DDEVICE9EX iface, HWND hDestinationWindow) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p) Stub!\n", This, hDestinationWindow); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateRenderTargetEx(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Lockable, IDirect3DSurface9 ** ppSurface, HANDLE *pSharedHandle, DWORD Usage) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d, %d, %d, %d, %d, %s, %p, %p, 0x%08x) Stub!\n", This, Width, Height, Format, MultiSample, MultiSampleQuality, Lockable ? "true" : "false", ppSurface, pSharedHandle, Usage); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d, %d, %d, %d, %p, %p, 0x%08x) Stub!\n", This, Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d, %d, %d, %d, %d, %s, %p, %p, 0x%08x) Stub!\n", This, Width, Height, Format, MultiSample, MultiSampleQuality, Discard ? "true" : "false", ppSurface, pSharedHandle, Usage); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_ResetEx(LPDIRECT3DDEVICE9EX iface, D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%p) Stub!\n", This, pPresentationParameters); + return WINED3DERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirect3DDevice9ExImpl_GetDisplayModeEx(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *) iface; + FIXME("(%p)->(%d, %p, %p) Stub!\n", This, iSwapChain, pMode, pRotation); + return WINED3DERR_INVALIDCALL; +} + +const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl = { /* IUnknown */ IDirect3DDevice9Impl_QueryInterface, @@ -1449,7 +1679,23 @@ const IDirect3DDevice9Vtbl Direct3DDevice9_Vtbl = IDirect3DDevice9Impl_DrawRectPatch, IDirect3DDevice9Impl_DrawTriPatch, IDirect3DDevice9Impl_DeletePatch, - IDirect3DDevice9Impl_CreateQuery + IDirect3DDevice9Impl_CreateQuery, + /* IDirect3DDevice9Ex */ + IDirect3DDevice9ExImpl_SetConvolutionMonoKernel, + IDirect3DDevice9ExImpl_ComposeRects, + IDirect3DDevice9ExImpl_PresentEx, + IDirect3DDevice9ExImpl_GetGPUThreadPriority, + IDirect3DDevice9ExImpl_SetGPUThreadPriority, + IDirect3DDevice9ExImpl_WaitForVBlank, + IDirect3DDevice9ExImpl_CheckresourceResidency, + IDirect3DDevice9ExImpl_SetMaximumFrameLatency, + IDirect3DDevice9ExImpl_GetMaximumFrameLatency, + IDirect3DDevice9ExImpl_CheckdeviceState, + IDirect3DDevice9ExImpl_CreateRenderTargetEx, + IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx, + IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx, + IDirect3DDevice9ExImpl_ResetEx, + IDirect3DDevice9ExImpl_GetDisplayModeEx }; @@ -1467,7 +1713,7 @@ HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT Lockable = FALSE; TRACE("relay\n"); - res = IDirect3DDevice9Impl_CreateSurface((IDirect3DDevice9 *)device, Width, Height, (D3DFORMAT)Format, + res = IDirect3DDevice9Impl_CreateSurface((IDirect3DDevice9Ex *)device, Width, Height, (D3DFORMAT)Format, Lockable, FALSE/*Discard*/, Level, (IDirect3DSurface9 **)&d3dSurface, D3DRTYPE_SURFACE, Usage, (D3DPOOL) Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */, pSharedHandle); diff --git a/reactos/dll/directx/wine/d3d9/directx.c b/reactos/dll/directx/wine/d3d9/directx.c index 28268f81684..b605f44da7a 100644 --- a/reactos/dll/directx/wine/d3d9/directx.c +++ b/reactos/dll/directx/wine/d3d9/directx.c @@ -25,7 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d9); /* IDirect3D9 IUnknown parts follow: */ -static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID riid, LPVOID* ppobj) +static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9EX iface, REFIID riid, LPVOID* ppobj) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; @@ -33,7 +33,19 @@ static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID ri || IsEqualGUID(riid, &IID_IDirect3D9)) { IUnknown_AddRef(iface); *ppobj = This; + TRACE("Returning IDirect3D9 interface at %p\n", *ppobj); return S_OK; + } else if(IsEqualGUID(riid, &IID_IDirect3D9Ex)) { + if(This->extended) { + *ppobj = (IDirect3D9Ex *) This; + TRACE("Returning IDirect3D9Ex interface at %p\n", *ppobj); + IDirect3D9Ex_AddRef((IDirect3D9Ex *)*ppobj); + } else { + WARN("Application asks for IDirect3D9Ex, but this instance wasn't created with Direct3DCreate9Ex\n"); + WARN("Returning E_NOINTERFACE\n"); + *ppobj = NULL; + return E_NOINTERFACE; + } } WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj); @@ -41,7 +53,7 @@ static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID ri return E_NOINTERFACE; } -static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) { +static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9EX iface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; ULONG ref = InterlockedIncrement(&This->ref); @@ -50,7 +62,7 @@ static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) { return ref; } -static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) { +static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9EX iface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); @@ -67,7 +79,7 @@ static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) { } /* IDirect3D9 Interface follow: */ -static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9 iface, void* pInitializeFunction) { +static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9EX iface, void* pInitializeFunction) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("(%p)->(%p)\n", This, pInitializeFunction); @@ -78,7 +90,7 @@ static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9 iface, return hr; } -static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9 iface) { +static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9EX iface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("%p\n", This); @@ -89,7 +101,7 @@ static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9 iface) { return hr; } -static HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9 iface, UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) { +static HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9EX iface, UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; WINED3DADAPTER_IDENTIFIER adapter_id; HRESULT hr; @@ -114,7 +126,7 @@ static HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9 iface, UIN return hr; } -static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format) { +static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9EX iface, UINT Adapter, D3DFORMAT Format) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("(%p)->(%d, %d\n", This, Adapter, Format); @@ -130,7 +142,7 @@ static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Ad return hr; } -static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { +static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9EX iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("(%p)->(%d, %d, %d, %p)\n", This, Adapter, Format, Mode, pMode); @@ -145,12 +157,12 @@ static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Ad return hr; } -static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9 iface, UINT Adapter, D3DDISPLAYMODE* pMode) { +static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9EX iface, UINT Adapter, D3DDISPLAYMODE* pMode) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; return IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, (WINED3DDISPLAYMODE *) pMode); } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface, +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; @@ -165,7 +177,7 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface, return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface, +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; @@ -174,12 +186,12 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface, EnterCriticalSection(&d3d9_cs); hr = IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, AdapterFormat, - Usage, RType, CheckFormat); + Usage, RType, CheckFormat, SURFACE_OPENGL); LeaveCriticalSection(&d3d9_cs); return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 iface, +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; @@ -193,7 +205,7 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 ifac return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9 iface, +static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; @@ -207,7 +219,7 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9 iface, return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) { +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("%p\n", This); @@ -276,7 +288,7 @@ void filter_caps(D3DCAPS9* pCaps) D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV; } -static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { +static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hrc = D3D_OK; WINED3DCAPS *pWineCaps; @@ -291,10 +303,10 @@ static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapt return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/ } memset(pCaps, 0, sizeof(*pCaps)); - D3D9CAPSTOWINECAPS(pCaps, pWineCaps) EnterCriticalSection(&d3d9_cs); hrc = IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, pWineCaps); LeaveCriticalSection(&d3d9_cs); + WINECAPSTOD3D9CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */ @@ -306,7 +318,7 @@ static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapt return hrc; } -static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapter) { +static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9EX iface, UINT Adapter) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HMONITOR ret; TRACE("%p\n", This); @@ -447,7 +459,7 @@ ULONG WINAPI D3D9CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) { return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent); } -static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, +static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { @@ -540,9 +552,39 @@ static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapte return hr; } +static UINT WINAPI IDirect3D9ExImpl_GetAdapterModeCountEx(IDirect3D9Ex *iface, UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter) { + IDirect3D9Impl *This = (IDirect3D9Impl *)iface; + FIXME("(%p)->(%d, %p): Stub!\n", This, Adapter, pFilter); + return D3DERR_DRIVERINTERNALERROR; +} + +static HRESULT WINAPI IDirect3D9ExImpl_EnumAdapterModesEx(IDirect3D9Ex *iface, UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) { + IDirect3D9Impl *This = (IDirect3D9Impl *)iface; + FIXME("(%p)->(%d, %p, %p): Stub!\n", This, Adapter, pFilter, pMode); + return D3DERR_DRIVERINTERNALERROR; +} + +static HRESULT WINAPI IDirect3D9ExImpl_GetAdapterDisplayModeEx(IDirect3D9Ex *iface, UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) { + IDirect3D9Impl *This = (IDirect3D9Impl *)iface; + FIXME("(%p)->(%d, %p, %p): Stub!\n", This, Adapter, pMode, pRotation); + return D3DERR_DRIVERINTERNALERROR; +} + +static HRESULT WINAPI IDirect3D9ExImpl_CreateDeviceEx(IDirect3D9Ex *iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, struct IDirect3DDevice9Ex **ppReturnedDeviceInterface) { + IDirect3D9Impl *This = (IDirect3D9Impl *)iface; + FIXME("(%p)->(%d, %d, %p, 0x%08x, %p, %p, %p): Stub!\n", This, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, ppReturnedDeviceInterface); + *ppReturnedDeviceInterface = NULL; + return D3DERR_DRIVERINTERNALERROR; +} + +static HRESULT WINAPI IDirect3D9ExImpl_GetAdapterLUID(IDirect3D9Ex *iface, UINT Adapter, LUID *pLUID) { + IDirect3D9Impl *This = (IDirect3D9Impl *)iface; + FIXME("(%p)->(%d, %p)\n", This, Adapter, pLUID); + return D3DERR_DRIVERINTERNALERROR; +} -const IDirect3D9Vtbl Direct3D9_Vtbl = +const IDirect3D9ExVtbl Direct3D9_Vtbl = { /* IUnknown */ IDirect3D9Impl_QueryInterface, @@ -562,5 +604,12 @@ const IDirect3D9Vtbl Direct3D9_Vtbl = IDirect3D9Impl_CheckDeviceFormatConversion, IDirect3D9Impl_GetDeviceCaps, IDirect3D9Impl_GetAdapterMonitor, - IDirect3D9Impl_CreateDevice + IDirect3D9Impl_CreateDevice, + /* IDirect3D9Ex */ + IDirect3D9ExImpl_GetAdapterModeCountEx, + IDirect3D9ExImpl_EnumAdapterModesEx, + IDirect3D9ExImpl_GetAdapterDisplayModeEx, + IDirect3D9ExImpl_CreateDeviceEx, + IDirect3D9ExImpl_GetAdapterLUID + }; diff --git a/reactos/dll/directx/wine/d3d9/indexbuffer.c b/reactos/dll/directx/wine/d3d9/indexbuffer.c index d886bd7db89..1193c6ae1cb 100644 --- a/reactos/dll/directx/wine/d3d9/indexbuffer.c +++ b/reactos/dll/directx/wine/d3d9/indexbuffer.c @@ -211,7 +211,7 @@ static const IDirect3DIndexBuffer9Vtbl Direct3DIndexBuffer9_Vtbl = /* IDirect3DDevice9 IDirect3DIndexBuffer9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9 iface, +HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9EX iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) { diff --git a/reactos/dll/directx/wine/d3d9/pixelshader.c b/reactos/dll/directx/wine/d3d9/pixelshader.c index 8eeb3d60bf6..919b5a7c8e8 100644 --- a/reactos/dll/directx/wine/d3d9/pixelshader.c +++ b/reactos/dll/directx/wine/d3d9/pixelshader.c @@ -106,7 +106,7 @@ static const IDirect3DPixelShader9Vtbl Direct3DPixelShader9_Vtbl = /* IDirect3DDevice9 IDirect3DPixelShader9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9 iface, CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) { +HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9EX iface, CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DPixelShader9Impl *object; HRESULT hrc = D3D_OK; @@ -146,7 +146,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9 iface, C return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9* pShader) { +HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9EX iface, IDirect3DPixelShader9* pShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DPixelShader9Impl *shader = (IDirect3DPixelShader9Impl *)pShader; TRACE("(%p) Relay\n", This); @@ -157,7 +157,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9 iface, IDir return D3D_OK; } -HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9** ppShader) { +HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9EX iface, IDirect3DPixelShader9** ppShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DPixelShader *object; @@ -182,7 +182,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9 iface, IDir return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -193,13 +193,13 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9 if return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, float* pConstantData, UINT Vector4fCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT Register, float* pConstantData, UINT Vector4fCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); return IWineD3DDevice_GetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount); } -HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, CONST int* pConstantData, UINT Vector4iCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST int* pConstantData, UINT Vector4iCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -210,7 +210,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9 if return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, int* pConstantData, UINT Vector4iCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT Register, int* pConstantData, UINT Vector4iCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -221,7 +221,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9 if return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, CONST BOOL* pConstantData, UINT BoolCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST BOOL* pConstantData, UINT BoolCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -232,7 +232,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9 if return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, BOOL* pConstantData, UINT BoolCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT Register, BOOL* pConstantData, UINT BoolCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); diff --git a/reactos/dll/directx/wine/d3d9/query.c b/reactos/dll/directx/wine/d3d9/query.c index 94cd7ec7273..9eeabc80ca1 100644 --- a/reactos/dll/directx/wine/d3d9/query.c +++ b/reactos/dll/directx/wine/d3d9/query.c @@ -145,7 +145,7 @@ static const IDirect3DQuery9Vtbl Direct3DQuery9_Vtbl = /* IDirect3DDevice9 IDirect3DQuery9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9 iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) { +HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9EX iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DQuery9Impl *object = NULL; HRESULT hr = D3D_OK; diff --git a/reactos/dll/directx/wine/d3d9/stateblock.c b/reactos/dll/directx/wine/d3d9/stateblock.c index 33eda64b0f1..89e992c2698 100644 --- a/reactos/dll/directx/wine/d3d9/stateblock.c +++ b/reactos/dll/directx/wine/d3d9/stateblock.c @@ -115,7 +115,7 @@ static const IDirect3DStateBlock9Vtbl Direct3DStateBlock9_Vtbl = /* IDirect3DDevice9 IDirect3DStateBlock9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9 iface, D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppStateBlock) { +HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9EX iface, D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppStateBlock) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DStateBlock9Impl* object; HRESULT hrc = D3D_OK; @@ -149,7 +149,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9 iface, D3 return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9 iface) { +HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); @@ -160,7 +160,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9 iface) { return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9 iface, IDirect3DStateBlock9** ppSB) { +HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9EX iface, IDirect3DStateBlock9** ppSB) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; IWineD3DStateBlock* wineD3DStateBlock; @@ -168,7 +168,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9 iface, IDi TRACE("(%p) Relay\n", This); - /* Tell wineD3D to endstatablock before anything else (in case we run out + /* Tell wineD3D to endstateblock before anything else (in case we run out * of memory later and cause locking problems) */ EnterCriticalSection(&d3d9_cs); diff --git a/reactos/dll/directx/wine/d3d9/swapchain.c b/reactos/dll/directx/wine/d3d9/swapchain.c index 79bea2da2ec..0dd9b8f2d17 100644 --- a/reactos/dll/directx/wine/d3d9/swapchain.c +++ b/reactos/dll/directx/wine/d3d9/swapchain.c @@ -191,7 +191,7 @@ static const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl = /* IDirect3DDevice9 IDirect3DSwapChain9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) { +HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE9EX iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DSwapChain9Impl* object; HRESULT hrc = D3D_OK; @@ -229,7 +229,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE localParameters.PresentationInterval = pPresentationParameters->PresentationInterval; EnterCriticalSection(&d3d9_cs); - hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D9CB_CreateRenderTarget, D3D9CB_CreateDepthStencilSurface); + hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D9CB_CreateRenderTarget, D3D9CB_CreateDepthStencilSurface, SURFACE_OPENGL); LeaveCriticalSection(&d3d9_cs); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; @@ -260,7 +260,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) { +HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; IWineD3DSwapChain *swapchain = NULL; @@ -279,7 +279,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9 iface, UINT return hrc; } -UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9 iface) { +UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; UINT ret; TRACE("(%p) Relay\n", This); diff --git a/reactos/dll/directx/wine/d3d9/texture.c b/reactos/dll/directx/wine/d3d9/texture.c index aa873ebfc72..a8a525a7711 100644 --- a/reactos/dll/directx/wine/d3d9/texture.c +++ b/reactos/dll/directx/wine/d3d9/texture.c @@ -327,7 +327,7 @@ static const IDirect3DTexture9Vtbl Direct3DTexture9_Vtbl = /* IDirect3DDevice9 IDirect3DTexture9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, +HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) { IDirect3DTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; diff --git a/reactos/dll/directx/wine/d3d9/vertexbuffer.c b/reactos/dll/directx/wine/d3d9/vertexbuffer.c index 771695147a5..12ecd0baeea 100644 --- a/reactos/dll/directx/wine/d3d9/vertexbuffer.c +++ b/reactos/dll/directx/wine/d3d9/vertexbuffer.c @@ -207,7 +207,7 @@ static const IDirect3DVertexBuffer9Vtbl Direct3DVertexBuffer9_Vtbl = /* IDirect3DDevice9 IDirect3DVertexBuffer9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9 iface, +HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9EX iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) { diff --git a/reactos/dll/directx/wine/d3d9/vertexdeclaration.c b/reactos/dll/directx/wine/d3d9/vertexdeclaration.c index 3973c98fbf9..327c7417e8e 100644 --- a/reactos/dll/directx/wine/d3d9/vertexdeclaration.c +++ b/reactos/dll/directx/wine/d3d9/vertexdeclaration.c @@ -71,7 +71,7 @@ HRESULT vdecl_convert_fvf( BOOL has_specular = (fvf & D3DFVF_SPECULAR) !=0; DWORD num_textures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; - DWORD texcoords = (fvf & 0x00FF0000) >> 16; + DWORD texcoords = (fvf & 0xFFFF0000) >> 16; D3DVERTEXELEMENT9 end_element = D3DDECL_END(); D3DVERTEXELEMENT9 *elements = NULL; @@ -89,7 +89,7 @@ HRESULT vdecl_convert_fvf( if (!elements) return D3DERR_OUTOFVIDEOMEMORY; - memcpy(&elements[size-1], &end_element, sizeof(D3DVERTEXELEMENT9)); + elements[size-1] = end_element; idx = 0; if (has_pos) { if (!has_blend && (fvf & D3DFVF_XYZRHW)) { @@ -231,7 +231,7 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECL TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - IDirect3DDevice9 *parentDevice = This->parentDevice; + IDirect3DDevice9Ex *parentDevice = This->parentDevice; if(!This->convFVF) { IDirect3DVertexDeclaration9Impl_Release(iface); @@ -289,10 +289,10 @@ static const IDirect3DVertexDeclaration9Vtbl Direct3DVertexDeclaration9_Vtbl = IDirect3DVertexDeclaration9Impl_GetDeclaration }; -static size_t convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elements, WINED3DVERTEXELEMENT **wined3d_elements) { +static UINT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elements, WINED3DVERTEXELEMENT **wined3d_elements) { const D3DVERTEXELEMENT9* element; - size_t element_count = 1; - size_t i; + UINT element_count = 1; + UINT i; TRACE("d3d9_elements %p, wined3d_elements %p\n", d3d9_elements, wined3d_elements); @@ -318,12 +318,12 @@ static size_t convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_eleme } /* IDirect3DDevice9 IDirect3DVertexDeclaration9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) { +HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9EX iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DVertexDeclaration9Impl *object = NULL; WINED3DVERTEXELEMENT* wined3d_elements; - size_t element_count; + UINT element_count; HRESULT hr = D3D_OK; TRACE("(%p) : Relay\n", iface); @@ -368,7 +368,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 if (FAILED(hr)) { /* free up object */ - FIXME("(%p) call to IWineD3DDevice_CreateVertexDeclaration failed\n", This); + WARN("(%p) call to IWineD3DDevice_CreateVertexDeclaration failed\n", This); HeapFree(GetProcessHeap(), 0, object->elements); HeapFree(GetProcessHeap(), 0, object); } else { @@ -380,7 +380,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9* pDecl) { +HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexDeclaration9* pDecl) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DVertexDeclaration9Impl *pDeclImpl = (IDirect3DVertexDeclaration9Impl *)pDecl; HRESULT hr = D3D_OK; @@ -393,7 +393,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 ifa return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9** ppDecl) { +HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexDeclaration9** ppDecl) { IDirect3DDevice9Impl* This = (IDirect3DDevice9Impl*) iface; IWineD3DVertexDeclaration* pTest = NULL; HRESULT hr = D3D_OK; diff --git a/reactos/dll/directx/wine/d3d9/vertexshader.c b/reactos/dll/directx/wine/d3d9/vertexshader.c index 8c73d3fd055..c41b2c4f74f 100644 --- a/reactos/dll/directx/wine/d3d9/vertexshader.c +++ b/reactos/dll/directx/wine/d3d9/vertexshader.c @@ -109,7 +109,7 @@ static const IDirect3DVertexShader9Vtbl Direct3DVertexShader9_Vtbl = /* IDirect3DDevice9 IDirect3DVertexShader9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9 iface, CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) { +HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9EX iface, CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; IDirect3DVertexShader9Impl *object; @@ -144,7 +144,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9 iface, return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9 iface, IDirect3DVertexShader9* pShader) { +HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexShader9* pShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; @@ -157,7 +157,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9 iface, IDi return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9 iface, IDirect3DVertexShader9** ppShader) { +HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9EX iface, IDirect3DVertexShader9** ppShader) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DVertexShader *pShader; HRESULT hrc = D3D_OK; @@ -176,7 +176,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9 iface, IDi return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); @@ -187,7 +187,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9 i return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, float* pConstantData, UINT Vector4fCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT Register, float* pConstantData, UINT Vector4fCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; @@ -198,7 +198,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9 i return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, CONST int* pConstantData, UINT Vector4iCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST int* pConstantData, UINT Vector4iCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); @@ -209,7 +209,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9 i return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, int* pConstantData, UINT Vector4iCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9EX iface, UINT Register, int* pConstantData, UINT Vector4iCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); @@ -220,7 +220,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9 i return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, CONST BOOL* pConstantData, UINT BoolCount) { +HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST BOOL* pConstantData, UINT BoolCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); @@ -231,7 +231,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9 i return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, BOOL* pConstantData, UINT BoolCount) { +HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(LPDIRECT3DDEVICE9EX iface, UINT Register, BOOL* pConstantData, UINT BoolCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) : Relay\n", This); diff --git a/reactos/dll/directx/wine/d3d9/volume.c b/reactos/dll/directx/wine/d3d9/volume.c index 1a6f32daa78..2af611d9719 100644 --- a/reactos/dll/directx/wine/d3d9/volume.c +++ b/reactos/dll/directx/wine/d3d9/volume.c @@ -205,7 +205,7 @@ HRESULT WINAPI D3D9CB_CreateVolume(IUnknown *pDevice, IUnknown *pSuperior, UINT HeapFree(GetProcessHeap(), 0, object); *ppVolume = NULL; } else { - *ppVolume = (IWineD3DVolume *)object->wineD3DVolume; + *ppVolume = object->wineD3DVolume; object->container = pSuperior; object->forwardReference = pSuperior; } diff --git a/reactos/dll/directx/wine/d3d9/volumetexture.c b/reactos/dll/directx/wine/d3d9/volumetexture.c index cf73f7a9467..28a7460fb7d 100644 --- a/reactos/dll/directx/wine/d3d9/volumetexture.c +++ b/reactos/dll/directx/wine/d3d9/volumetexture.c @@ -238,7 +238,7 @@ static const IDirect3DVolumeTexture9Vtbl Direct3DVolumeTexture9_Vtbl = /* IDirect3DDevice9 IDirect3DVolumeTexture9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9 iface, +HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) { diff --git a/reactos/dll/directx/wine/wined3d/arb_program_shader.c b/reactos/dll/directx/wine/wined3d/arb_program_shader.c index b044f31e1e8..2bb70c30a12 100644 --- a/reactos/dll/directx/wine/wined3d/arb_program_shader.c +++ b/reactos/dll/directx/wine/wined3d/arb_program_shader.c @@ -9,6 +9,7 @@ * Copyright 2006 Ivan Gyurdiev * Copyright 2006 Jason Green * Copyright 2006 Henri Verbeet + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,9 +35,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); +WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); #define GLINFO_LOCATION (*gl_info) +/* Internally used shader constants. Applications can use constants 0 to GL_LIMITS(vshader_constantsF) - 1, + * so upload them above that + */ +#define ARB_SHADER_PRIVCONST_BASE GL_LIMITS(vshader_constantsF) +#define ARB_SHADER_PRIVCONST_POS ARB_SHADER_PRIVCONST_BASE + 0 + +/* ARB_program_shader private data */ +struct shader_arb_priv { + GLuint current_vprogram_id; + GLuint current_fprogram_id; + GLuint depth_blt_vprogram_id; + GLuint depth_blt_fprogram_id; + BOOL use_arbfp_fixed_func; + struct hash_table_t *fragment_shaders; +}; + /******************************************************** * ARB_[vertex/fragment]_program helper functions follow ********************************************************/ @@ -48,79 +66,98 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders) * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders) */ -static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type, - unsigned int max_constants, float* constants, struct list *constant_list) { - constants_entry *constant; +static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type, + unsigned int max_constants, float* constants, char *dirty_consts) { local_constant* lconst; - DWORD i, j, k; - DWORD *idx; + DWORD i, j; + unsigned int ret; if (TRACE_ON(d3d_shader)) { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i, + for(i = 0; i < max_constants; i++) { + if(!dirty_consts[i]) continue; + TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i, constants[i * 4 + 0], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]); - } } } /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */ if(target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) { float lcl_const[4]; - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - k = i * 4; - if(constants[k + 0] > 1.0) lcl_const[0] = 1.0; - else if(constants[k + 0] < -1.0) lcl_const[0] = -1.0; - else lcl_const[0] = constants[k + 0]; + for(i = 0; i < max_constants; i++) { + if(!dirty_consts[i]) continue; + dirty_consts[i] = 0; - if(constants[k + 1] > 1.0) lcl_const[1] = 1.0; - else if(constants[k + 1] < -1.0) lcl_const[1] = -1.0; - else lcl_const[1] = constants[k + 1]; + j = 4 * i; + if(constants[j + 0] > 1.0) lcl_const[0] = 1.0; + else if(constants[j + 0] < -1.0) lcl_const[0] = -1.0; + else lcl_const[0] = constants[j + 0]; - if(constants[k + 2] > 1.0) lcl_const[2] = 1.0; - else if(constants[k + 2] < -1.0) lcl_const[2] = -1.0; - else lcl_const[2] = constants[k + 2]; + if(constants[j + 1] > 1.0) lcl_const[1] = 1.0; + else if(constants[j + 1] < -1.0) lcl_const[1] = -1.0; + else lcl_const[1] = constants[j + 1]; - if(constants[k + 3] > 1.0) lcl_const[3] = 1.0; - else if(constants[k + 3] < -1.0) lcl_const[3] = -1.0; - else lcl_const[3] = constants[k + 3]; + if(constants[j + 2] > 1.0) lcl_const[2] = 1.0; + else if(constants[j + 2] < -1.0) lcl_const[2] = -1.0; + else lcl_const[2] = constants[j + 2]; - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); - } + if(constants[j + 3] > 1.0) lcl_const[3] = 1.0; + else if(constants[j + 3] < -1.0) lcl_const[3] = -1.0; + else lcl_const[3] = constants[j + 3]; + + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); } } else { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); + if(GL_SUPPORT(EXT_GPU_PROGRAM_PARAMETERS)) { + /* TODO: Benchmark if we're better of with finding the dirty constants ourselves, + * or just reloading *all* constants at once + * + GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, 0, max_constants, constants)); + */ + for(i = 0; i < max_constants; i++) { + if(!dirty_consts[i]) continue; + + /* Find the next block of dirty constants */ + dirty_consts[i] = 0; + j = i; + for(i++; (i < max_constants) && dirty_consts[i]; i++) { + dirty_consts[i] = 0; + } + + GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4))); + } + } else { + for(i = 0; i < max_constants; i++) { + if(dirty_consts[i]) { + dirty_consts[i] = 0; + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); + } } } } checkGLcall("glProgramEnvParameter4fvARB()"); /* Load immediate constants */ - if (TRACE_ON(d3d_shader)) { - LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - GLfloat* values = (GLfloat*)lconst->value; - TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx, - values[0], values[1], values[2], values[3]); + if(This->baseShader.load_local_constsF) { + if (TRACE_ON(d3d_shader)) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + GLfloat* values = (GLfloat*)lconst->value; + TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx, + values[0], values[1], values[2], values[3]); + } } + /* Immediate constants are clamped for 1.X shaders at loading times */ + ret = 0; + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + dirty_consts[lconst->idx] = 1; /* Dirtify so the non-immediate constant overwrites it next time */ + ret = max(ret, lconst->idx + 1); + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value)); + } + checkGLcall("glProgramEnvParameter4fvARB()"); + return ret; /* The loaded immediate constants need reloading for the next shader */ + } else { + return 0; /* No constants are dirty now */ } - /* Immediate constants are clamped for 1.X shaders at loading times */ - LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value)); - } - checkGLcall("glProgramEnvParameter4fvARB()"); } /** @@ -129,7 +166,7 @@ static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_ * We only support float constants in ARB at the moment, so don't * worry about the Integers or Booleans */ -void shader_arb_load_constants( +static void shader_arb_load_constants( IWineD3DDevice* device, char usePixelShader, char useVertexShader) { @@ -137,15 +174,17 @@ void shader_arb_load_constants( IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; + unsigned char i; if (useVertexShader) { IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; /* Load DirectX 9 float constants for vertex shader */ - shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB, - GL_LIMITS(vshader_constantsF), - stateBlock->vertexShaderConstantF, - &stateBlock->set_vconstantsF); + deviceImpl->highest_dirty_vs_const = shader_arb_load_constantsF( + vshader, gl_info, GL_VERTEX_PROGRAM_ARB, + deviceImpl->highest_dirty_vs_const, + stateBlock->vertexShaderConstantF, + deviceImpl->activeContext->vshader_const_dirty); /* Upload the position fixup */ GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, deviceImpl->posFixup)); @@ -157,28 +196,31 @@ void shader_arb_load_constants( IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader; /* Load DirectX 9 float constants for pixel shader */ - shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, - GL_LIMITS(pshader_constantsF), - stateBlock->pixelShaderConstantF, - &stateBlock->set_pconstantsF); - if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst != -1) { - /* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the - * number of the constant to load the matrix into. - * The state manager takes care that this function is always called if the bump env matrix changes - */ - float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; - GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data)); + deviceImpl->highest_dirty_ps_const = shader_arb_load_constantsF( + pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, + deviceImpl->highest_dirty_ps_const, + stateBlock->pixelShaderConstantF, + deviceImpl->activeContext->pshader_const_dirty); - if(((IWineD3DPixelShaderImpl *) pshader)->luminanceconst != -1) { + for(i = 0; i < psi->numbumpenvmatconsts; i++) { + /* The state manager takes care that this function is always called if the bump env matrix changes + */ + float *data = (float *) &stateBlock->textureState[(int) psi->bumpenvmatconst[i].texunit][WINED3DTSS_BUMPENVMAT00]; + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst[i].const_num, data)); + deviceImpl->activeContext->pshader_const_dirty[psi->bumpenvmatconst[i].const_num] = 1; + + if(psi->luminanceconst[i].const_num != -1) { /* WINED3DTSS_BUMPENVLSCALE and WINED3DTSS_BUMPENVLOFFSET are next to each other. * point gl to the scale, and load 4 floats. x = scale, y = offset, z and w are junk, we * don't care about them. The pointers are valid for sure because the stateblock is bigger. * (they're WINED3DTSS_TEXTURETRANSFORMFLAGS and WINED3DTSS_ADDRESSW, so most likely 0 or NaN */ - float *scale = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVLSCALE]; - GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst, scale)); + float *scale = (float *) &stateBlock->textureState[(int) psi->luminanceconst[i].texunit][WINED3DTSS_BUMPENVLSCALE]; + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst[i].const_num, scale)); + deviceImpl->activeContext->pshader_const_dirty[psi->luminanceconst[i].const_num] = 1; } } + if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { float comparison[4]; @@ -200,12 +242,15 @@ void shader_arb_load_constants( GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_cmp_const, comparison)); GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_low_const, mul_low)); checkGLcall("Load sRGB correction constants\n"); + deviceImpl->activeContext->pshader_const_dirty[psi->srgb_low_const] = 1; + deviceImpl->activeContext->pshader_const_dirty[psi->srgb_cmp_const] = 1; + } } } /* Generate the variable & register declarations for the ARB_vertex_program output target */ -void shader_generate_arb_declarations( +static void shader_generate_arb_declarations( IWineD3DBaseShader *iface, shader_reg_maps* reg_maps, SHADER_BUFFER* buffer, @@ -213,11 +258,12 @@ void shader_generate_arb_declarations( IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; - DWORD i; + DWORD i, cur; char pshader = shader_is_pshader_version(This->baseShader.hex_version); unsigned max_constantsF = min(This->baseShader.limits.constant_float, (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF))); UINT extra_constants_needed = 0; + local_constant* lconst; /* Temporary Output register */ shader_addline(buffer, "TEMP TMP_OUT;\n"); @@ -243,29 +289,41 @@ void shader_generate_arb_declarations( shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i); } - ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = -1; - ((IWineD3DPixelShaderImpl *)This)->luminanceconst = -1; - if(reg_maps->bumpmat != -1 /* Only a pshader can use texbem */) { + for(i = 0; i < (sizeof(reg_maps->bumpmat) / sizeof(reg_maps->bumpmat[0])); i++) { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This; + if(!reg_maps->bumpmat[i]) continue; + + cur = ps->numbumpenvmatconsts; + ps->bumpenvmatconst[cur].const_num = -1; + ps->bumpenvmatconst[cur].texunit = i; + ps->luminanceconst[cur].const_num = -1; + ps->luminanceconst[cur].texunit = i; + /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying * bump mapping. */ - if(max_constantsF < GL_LIMITS(pshader_constantsF)) { - ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = max_constantsF; - shader_addline(buffer, "PARAM bumpenvmat = program.env[%d];\n", ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst); + if(max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) { + ps->bumpenvmatconst[cur].const_num = max_constantsF + extra_constants_needed; + shader_addline(buffer, "PARAM bumpenvmat%d = program.env[%d];\n", + i, ps->bumpenvmatconst[cur].const_num); + extra_constants_needed++; - if(reg_maps->luminanceparams != -1 && max_constantsF +1 < GL_LIMITS(pshader_constantsF)) { - extra_constants_needed += 1; - ((IWineD3DPixelShaderImpl *)This)->luminanceconst = max_constantsF + 1; - shader_addline(buffer, "PARAM luminance = program.env[%d];\n", ((IWineD3DPixelShaderImpl *)This)->luminanceconst); - } else if(reg_maps->luminanceparams != -1) { + if(reg_maps->luminanceparams && max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) { + ((IWineD3DPixelShaderImpl *)This)->luminanceconst[cur].const_num = max_constantsF + extra_constants_needed; + shader_addline(buffer, "PARAM luminance%d = program.env[%d];\n", + i, ps->luminanceconst[cur].const_num); + extra_constants_needed++; + } else if(reg_maps->luminanceparams) { FIXME("No free constant to load the luminance parameters\n"); } } else { FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n"); } - extra_constants_needed += 1; + + ps->numbumpenvmatconsts = cur + 1; } + if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) { IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; /* If there are 2 constants left to use, use them to pass the sRGB correction values in. This way @@ -312,9 +370,33 @@ void shader_generate_arb_declarations( ps_impl->srgb_mode_hardcoded = 1; } - /* Need to PARAM the environment parameters (constants) so we can use relative addressing */ - shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n", - max_constantsF, max_constantsF - 1); + /* Load local constants using the program-local space, + * this avoids reloading them each time the shader is used + */ + if(!This->baseShader.load_local_constsF) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + shader_addline(buffer, "PARAM C%u = program.local[%u];\n", lconst->idx, + lconst->idx); + } + } + + /* we use the array-based constants array if the local constants are marked for loading, + * because then we use indirect addressing, or when the local constant list is empty, + * because then we don't know if we're using indirect addressing or not. If we're hardcoding + * local constants do not declare the loaded constants as an array because ARB compilers usually + * do not optimize unused constants away + */ + if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) { + /* Need to PARAM the environment parameters (constants) so we can use relative addressing */ + shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n", + max_constantsF, max_constantsF - 1); + } else { + for(i = 0; i < max_constantsF; i++) { + if(!shader_constant_is_local(This, i)) { + shader_addline(buffer, "PARAM C%d = program.env[%d];\n",i, i); + } + } + } } static const char * const shift_tab[] = { @@ -386,11 +468,12 @@ static void shader_arb_get_swizzle(const DWORD param, BOOL fixup, char *swizzle_ *ptr = '\0'; } -static void pshader_get_register_name( +static void pshader_get_register_name(IWineD3DBaseShader* iface, const DWORD param, char* regstr) { DWORD reg = param & WINED3DSP_REGNUM_MASK; DWORD regtype = shader_get_regtype(param); + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; switch (regtype) { case WINED3DSPR_TEMP: @@ -404,7 +487,11 @@ static void pshader_get_register_name( } break; case WINED3DSPR_CONST: - sprintf(regstr, "C[%u]", reg); + if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) { + sprintf(regstr, "C[%u]", reg); + } else { + sprintf(regstr, "C%u", reg); + } break; case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */ sprintf(regstr,"T%u", reg); @@ -474,7 +561,11 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param, sprintf(tmpReg, "C[A0.x - %u]", -reg + This->rel_offset); } } else { - sprintf(tmpReg, "C[%u]", reg); + if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) { + sprintf(tmpReg, "C[%u]", reg); + } else { + sprintf(tmpReg, "C%u", reg); + } } strcat(hwLine, tmpReg); break; @@ -525,8 +616,17 @@ static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const ch break; case WINED3DSTT_2D: - tex_type = "2D"; + { + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; + if(device->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + tex_type = "RECT"; + } else { + tex_type = "2D"; + } break; + } case WINED3DSTT_VOLUME: tex_type = "3D"; @@ -553,6 +653,155 @@ static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const ch } } +static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, const char *writemask, + const char *one, const char *two, WINED3DFORMAT fmt, + WineD3D_GL_Info *gl_info) { + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + if(GL_SUPPORT(NV_TEXTURE_SHADER) || + (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { + if(0) { + /* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) + * disabled until an application that needs it is found because it causes unneeded + * shader recompilation in some game + */ + if(strlen(writemask) >= 4) { + shader_addline(buffer, "MOV %s.%c, %s;\n", reg, writemask[3], one); + } + } + } else { + /* Correct the sign, but leave the blue as it is - it was loaded correctly already + * ARB shaders are a bit picky wrt writemasks and swizzles. If we're free to scale + * all registers, do so, this saves an instruction. + */ + if(strlen(writemask) >= 5) { + shader_addline(buffer, "MAD %s, %s, %s, -%s;\n", reg, reg, two, one); + } else if(strlen(writemask) >= 3) { + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], + reg, writemask[1], + two, one); + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[2], + reg, writemask[2], + two, one); + } else if(strlen(writemask) == 2) { + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", reg, writemask[1], + reg, writemask[1], two, one); + } + } + break; + + case WINED3DFMT_X8L8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Red and blue are the signed channels, fix them up; Blue(=L) is correct already, + * and a(X) is always 1.0. Cannot do a full conversion due to L(blue) + */ + if(strlen(writemask) >= 3) { + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], + reg, writemask[1], + two, one); + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[2], + reg, writemask[2], + two, one); + } else if(strlen(writemask) == 2) { + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], + reg, writemask[1], + two, one); + } + } + break; + + case WINED3DFMT_L6V5U5: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + if(strlen(writemask) >= 4) { + /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ + shader_addline(buffer, "MOV TMP.g, %s.%c;\n", + reg, writemask[2]); + shader_addline(buffer, "MAD %s.%c%c, %s.%c%c, %s, -%s;\n", + reg, writemask[1], writemask[1], + reg, writemask[1], writemask[3], + two, one); + shader_addline(buffer, "MOV %s.%c, TMP.g;\n", reg, + writemask[3]); + } else if(strlen(writemask) == 3) { + /* This is bad: We have VL, but we need VU */ + FIXME("2 components sampled from a converted L6V5U5 texture\n"); + } else { + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], + reg, writemask[1], + two, one); + } + } + break; + + case WINED3DFMT_Q8W8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Correct the sign in all channels */ + switch(strlen(writemask)) { + case 4: + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[3], + reg, writemask[3]); + /* drop through */ + case 3: + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[2], + reg, writemask[2]); + /* drop through */ + case 2: + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + break; + + /* Should not occur, since it's at minimum '.' and a letter */ + case 1: + ERR("Unexpected writemask: \"%s\"\n", writemask); + break; + + case 5: + default: + shader_addline(buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); + } + } + break; + + case WINED3DFMT_ATI2N: + /* GL_ATI_texture_compression_3dc returns the two channels as luminance-alpha, + * which means the first one is replicated across .rgb, and the 2nd one is in + * .a. We need the 2nd in .g + * + * GL_EXT_texture_compression_rgtc returns the values in .rg, however, they + * are swapped compared to d3d. So swap red and green. + */ + if(GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { + shader_addline(buffer, "SWZ %s, %s, %c, %c, 1, 0;\n", + reg, reg, writemask[2], writemask[1]); + } else { + if(strlen(writemask) == 5) { + shader_addline(buffer, "MOV %s.%c, %s.%c;\n", + reg, writemask[2], reg, writemask[4]); + } else if(strlen(writemask) == 2) { + /* Nothing to do */ + } else { + /* This is bad: We have VL, but we need VU */ + FIXME("2 or 3 components sampled from a converted ATI2N texture\n"); + } + } + break; + + /* stupid compiler */ + default: + break; + } +} + static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device; @@ -619,127 +868,17 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { shader->baseShader.sampled_format[sampler_idx] = conversion_group; } - pshader_get_register_name(arg->dst, reg); + pshader_get_register_name(arg->shader, arg->dst, reg); shader_arb_get_write_mask(arg, arg->dst, writemask); if(strlen(writemask) == 0) strcpy(writemask, ".xyzw"); - switch(fmt) { - case WINED3DFMT_V8U8: - case WINED3DFMT_V16U16: - if(GL_SUPPORT(NV_TEXTURE_SHADER) || - (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { -#if 0 - /* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) - * disabled until an application that needs it is found because it causes unneeded - * shader recompilation in some game - */ - if(strlen(writemask) >= 4) { - shader_addline(arg->buffer, "MOV %s.%c, one.z;\n", reg, writemask[3]); - } -#endif - } else { - /* Correct the sign, but leave the blue as it is - it was loaded correctly already - * ARB shaders are a bit picky wrt writemasks and swizzles. If we're free to scale - * all registers, do so, this saves an instruction. - */ - if(strlen(writemask) >= 5) { - shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); - } else if(strlen(writemask) >= 3) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[1], - reg, writemask[1]); - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[2], - reg, writemask[2]); - } else if(strlen(writemask) == 2) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[1], - reg, writemask[1]); - } - } - break; + gen_color_correction(arg->buffer, reg, writemask, "one", "coefmul.x", fmt, gl_info); - case WINED3DFMT_X8L8V8U8: - if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { - /* Red and blue are the signed channels, fix them up; Blue(=L) is correct already, - * and a(X) is always 1.0. Cannot do a full conversion due to L(blue) - */ - if(strlen(writemask) >= 3) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[1], - reg, writemask[1]); - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[2], - reg, writemask[2]); - } else if(strlen(writemask) == 2) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[1], - reg, writemask[1]); - } - } - break; - - case WINED3DFMT_L6V5U5: - if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { - if(strlen(writemask) >= 4) { - /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ - shader_addline(arg->buffer, "MOV TMP.g, %s.%c;\n", - reg, writemask[2]); - shader_addline(arg->buffer, "MAD %s.%c%c, %s.%c%c, coefmul.x, -one;\n", - reg, writemask[1], writemask[1], - reg, writemask[1], writemask[3]); - shader_addline(arg->buffer, "MOV %s.%c, TMP.g;\n", reg, - writemask[3]); - } else if(strlen(writemask) == 3) { - /* This is bad: We have VL, but we need VU */ - FIXME("2 components sampled from a converted L6V5U5 texture\n"); - } else { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[1], - reg, writemask[1]); - } - } - break; - - case WINED3DFMT_Q8W8V8U8: - if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { - /* Correct the sign in all channels */ - switch(strlen(writemask)) { - case 4: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[3], - reg, writemask[3]); - /* drop through */ - case 3: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[2], - reg, writemask[2]); - /* drop through */ - case 2: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", - reg, writemask[1], - reg, writemask[1]); - break; - - /* Should not occur, since it's at minimum '.' and a letter */ - case 1: - ERR("Unexpected writemask: \"%s\"\n", writemask); - break; - - case 5: - default: - shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); - } - } - break; - - /* stupid compiler */ - default: - break; - } } static void pshader_gen_input_modifier_line ( + IWineD3DBaseShader *iface, SHADER_BUFFER* buffer, const DWORD instr, int tmpreg, @@ -754,7 +893,7 @@ static void pshader_gen_input_modifier_line ( insert_line = 1; /* Get register name */ - pshader_get_register_name(instr, regstr); + pshader_get_register_name(iface, instr, regstr); shader_arb_get_swizzle(instr, FALSE, swzstr); switch (instr & WINED3DSP_SRCMOD_MASK) { @@ -824,19 +963,29 @@ void pshader_hw_bem(SHADER_OPCODE_ARG* arg) { char dst_name[50]; char src_name[2][50]; char dst_wmask[20]; + DWORD sampler_code = arg->dst & WINED3DSP_REGNUM_MASK; + BOOL has_bumpmat = FALSE; + int i; - pshader_get_register_name(arg->dst, dst_name); + for(i = 0; i < This->numbumpenvmatconsts; i++) { + if(This->bumpenvmatconst[i].const_num != -1 && This->bumpenvmatconst[i].texunit == sampler_code) { + has_bumpmat = TRUE; + break; + } + } + + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); strcat(dst_name, dst_wmask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); - pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[1], 1, src_name[1]); - if(This->bumpenvmatconst != -1) { + if(has_bumpmat) { /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ - shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n"); + shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", sampler_code); shader_addline(buffer, "DP3 TMP.r, TMP2, %s;\n", src_name[1]); - shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n"); + shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", sampler_code); shader_addline(buffer, "DP3 TMP.g, TMP2, %s;\n", src_name[1]); shader_addline(buffer, "ADD %s, %s, TMP;\n", dst_name, src_name[0]); @@ -858,13 +1007,13 @@ void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) { /* FIXME: support output modifiers */ /* Handle output register */ - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); /* Generate input register names (with modifiers) */ - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); - pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); - pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[1], 1, src_name[1]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]); /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */ if (shader->baseShader.hex_version <= WINED3DPS_VERSION(1, 3) && @@ -891,13 +1040,13 @@ void pshader_hw_cmp(SHADER_OPCODE_ARG* arg) { /* FIXME: support output modifiers */ /* Handle output register */ - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); /* Generate input register names (with modifiers) */ - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); - pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); - pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[1], 1, src_name[1]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]); shader_addline(buffer, "CMP%s %s%s, %s, %s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[0], src_name[2], src_name[1]); @@ -916,12 +1065,12 @@ void pshader_hw_dp2add(SHADER_OPCODE_ARG* arg) { DWORD shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; BOOL sat = (arg->dst & WINED3DSP_DSTMOD_MASK) & WINED3DSPDM_SATURATE; - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); - pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); - pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[1], 1, src_name[1]); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]); /* Emulate a DP2 with a DP3 and 0.0 */ shader_addline(buffer, "MOV TMP, %s;\n", src_name[0]); @@ -976,10 +1125,10 @@ void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) { /* Generate input register names (with modifiers) */ for (i = 1; i < curOpcode->num_params; ++i) - pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i]); + pshader_gen_input_modifier_line(arg->shader, buffer, src[i-1], i-1, operands[i]); /* Handle output register */ - pshader_get_register_name(dst, output_rname); + pshader_get_register_name(arg->shader, dst, output_rname); strcpy(operands[0], output_rname); shader_arb_get_write_mask(arg, dst, output_wmask); strcat(operands[0], output_wmask); @@ -1010,7 +1159,7 @@ void pshader_hw_texkill(SHADER_OPCODE_ARG* arg) { /* No swizzles are allowed in d3d's texkill. PS 1.x ignores the 4th component as documented, * but >= 2.0 honors it(undocumented, but tested by the d3d9 testsuit) */ - pshader_get_register_name(arg->dst, reg_dest); + pshader_get_register_name(arg->shader, arg->dst, reg_dest); if(hex_version >= WINED3DPS_VERSION(2,0)) { /* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */ @@ -1020,8 +1169,8 @@ void pshader_hw_texkill(SHADER_OPCODE_ARG* arg) { * copy the register into our general purpose TMP variable, overwrite .w and pass TMP to KIL */ shader_addline(buffer, "MOV TMP, %s;\n", reg_dest); - shader_addline(buffer, "MOV TMP.w, one.w;\n", reg_dest); - shader_addline(buffer, "KIL TMP;\n", reg_dest); + shader_addline(buffer, "MOV TMP.w, one.w;\n"); + shader_addline(buffer, "KIL TMP;\n"); } } @@ -1042,14 +1191,14 @@ void pshader_hw_tex(SHADER_OPCODE_ARG* arg) { /* All versions have a destination register */ reg_dest_code = dst & WINED3DSP_REGNUM_MASK; - pshader_get_register_name(dst, reg_dest); + pshader_get_register_name(arg->shader, dst, reg_dest); /* 1.0-1.3: Use destination register as coordinate source. 1.4+: Use provided coordinate source register. */ if (hex_version < WINED3DPS_VERSION(1,4)) strcpy(reg_coord, reg_dest); else - pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord); + pshader_gen_input_modifier_line(arg->shader, buffer, src[0], 0, reg_coord); /* 1.0-1.4: Use destination register number as texture code. 2.0+: Use provided sampler number as texure code. */ @@ -1105,7 +1254,7 @@ void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) { DWORD reg1 = dst & WINED3DSP_REGNUM_MASK; char reg_src[40]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, reg_src); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, reg_src); shader_addline(buffer, "MOV R%u%s, %s;\n", reg1, tmp, reg_src); } } @@ -1122,7 +1271,7 @@ void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) { char src_str[50]; sprintf(dst_str, "T%u", reg1); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_str); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str); shader_addline(buffer, "MOV TMP.r, %s.a;\n", src_str); shader_addline(buffer, "MOV TMP.g, %s.r;\n", src_str); flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; @@ -1132,40 +1281,35 @@ void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) { void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; - IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - DWORD flags; DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; char dst_str[8]; char src_str[50]; sprintf(dst_str, "T%u", reg1); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_str); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str); shader_addline(buffer, "MOV TMP.r, %s.g;\n", src_str); shader_addline(buffer, "MOV TMP.g, %s.b;\n", src_str); - flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; shader_hw_sample(arg, reg1, dst_str, "TMP", FALSE, FALSE); } void pshader_hw_texreg2rgb(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; - IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - DWORD flags; DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; char dst_str[8]; char src_str[50]; sprintf(dst_str, "T%u", reg1); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_str); - flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str); shader_hw_sample(arg, reg1, dst_str, src_str, FALSE, FALSE); } void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + BOOL has_bumpmat = FALSE; + BOOL has_luminance = FALSE; + int i; DWORD dst = arg->dst; DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK; @@ -1177,14 +1321,27 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { /* All versions have a destination register */ reg_dest_code = dst & WINED3DSP_REGNUM_MASK; /* Can directly use the name because texbem is only valid for <= 1.3 shaders */ - pshader_get_register_name(dst, reg_coord); + pshader_get_register_name(arg->shader, dst, reg_coord); - if(This->bumpenvmatconst != -1) { + for(i = 0; i < This->numbumpenvmatconsts; i++) { + if(This->bumpenvmatconst[i].const_num != -1 && reg_dest_code == This->bumpenvmatconst[i].texunit) { + has_bumpmat = TRUE; + break; + } + } + for(i = 0; i < This->numbumpenvmatconsts; i++) { + if(This->luminanceconst[i].const_num != -1 && reg_dest_code == This->luminanceconst[i].texunit) { + has_luminance = TRUE; + break; + } + } + + if(has_bumpmat) { /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ - shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n"); + shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code); shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src); - shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n"); + shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code); shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src); /* with projective textures, texbem only divides the static texture coord, not the displacement, @@ -1201,8 +1358,9 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE, FALSE); - if(arg->opcode->opcode == WINED3DSIO_TEXBEML && This->luminanceconst != -1) { - shader_addline(buffer, "MAD TMP, T%u.z, luminance.x, luminance.y;\n", src); + if(arg->opcode->opcode == WINED3DSIO_TEXBEML && has_luminance) { + shader_addline(buffer, "MAD TMP, T%u.z, luminance%d.x, luminance%d.y;\n", + src, reg_dest_code, reg_dest_code); shader_addline(buffer, "MUL %s, %s, TMP;\n", reg_coord, reg_coord); } @@ -1224,7 +1382,7 @@ void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; char src0_name[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", reg, src0_name); } @@ -1239,7 +1397,7 @@ void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) { char src0_name[50]; sprintf(dst_str, "T%u", reg); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", reg, src0_name); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; shader_hw_sample(arg, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); @@ -1253,7 +1411,7 @@ void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) { SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; char src0_name[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.%c, T%u, %s;\n", 'x' + current_state->current_row, reg, src0_name); current_state->texcoord_w[current_state->current_row++] = reg; } @@ -1269,7 +1427,7 @@ void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) { char dst_str[8]; char src0_name[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); /* Sample the texture using the calculated coordinates */ @@ -1290,7 +1448,7 @@ void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) { char dst_str[8]; char src0_name[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); /* Construct the eye-ray vector from w coordinates */ @@ -1327,7 +1485,7 @@ void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) { char dst_str[8]; char src0_name[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); /* Calculate reflection vector. @@ -1357,11 +1515,11 @@ void pshader_hw_texdepth(SHADER_OPCODE_ARG* arg) { char dst_name[50]; /* texdepth has an implicit destination, the fragment depth value. It's only parameter, - * which is essentially an input, is the destiantion register because it is the first - * param. According to the msdn, this must be register r5, but let's keep it more flexible + * which is essentially an input, is the destination register because it is the first + * parameter. According to the msdn, this must be register r5, but let's keep it more flexible * here */ - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); /* According to the msdn, the source register(must be r5) is unusable after * the texdepth instruction, so we're free to modify it @@ -1374,8 +1532,8 @@ void pshader_hw_texdepth(SHADER_OPCODE_ARG* arg) { */ shader_addline(buffer, "RCP %s.g, %s.g;\n", dst_name, dst_name); shader_addline(buffer, "MUL TMP.x, %s.r, %s.g;\n", dst_name, dst_name); - shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n", dst_name, dst_name); - shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n", dst_name, dst_name); + shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n"); + shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n"); } /** Process the WINED3DSIO_TEXDP3TEX instruction in ARB: @@ -1387,7 +1545,7 @@ void pshader_hw_texdp3tex(SHADER_OPCODE_ARG* arg) { char src0[50]; char dst_str[8]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0); shader_addline(buffer, "MOV TMP, 0.0;\n"); shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", sampler_idx, src0); @@ -1405,10 +1563,10 @@ void pshader_hw_texdp3(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; /* Handle output register */ - pshader_get_register_name(arg->dst, dst_str); + pshader_get_register_name(arg->shader, arg->dst, dst_str); shader_arb_get_write_mask(arg, arg->dst, dst_mask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0); shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dstreg, src0); /* TODO: Handle output modifiers */ @@ -1423,10 +1581,10 @@ void pshader_hw_texm3x3(SHADER_OPCODE_ARG* arg) { char src0[50]; DWORD dst_reg = arg->dst & WINED3DSP_REGNUM_MASK; - pshader_get_register_name(arg->dst, dst_str); + pshader_get_register_name(arg->shader, arg->dst, dst_str); shader_arb_get_write_mask(arg, arg->dst, dst_mask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0); shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst_reg, src0); shader_addline(buffer, "MOV %s%s, TMP;\n", dst_str, dst_mask); @@ -1443,7 +1601,7 @@ void pshader_hw_texm3x2depth(SHADER_OPCODE_ARG* arg) { DWORD dst_reg = arg->dst & WINED3DSP_REGNUM_MASK; char src0[50]; - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src0); shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", dst_reg, src0); /* How to deal with the special case dst_name.g == 0? if r != 0, then @@ -1537,10 +1695,10 @@ void shader_hw_nrm(SHADER_OPCODE_ARG* arg) { DWORD shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; BOOL sat = (arg->dst & WINED3DSP_DSTMOD_MASK) & WINED3DSPDM_SATURATE; - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name); shader_addline(buffer, "DP3 TMP, %s, %s;\n", src_name, src_name); shader_addline(buffer, "RSQ TMP, TMP.x;\n"); /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/ @@ -1553,7 +1711,7 @@ void shader_hw_nrm(SHADER_OPCODE_ARG* arg) { void shader_hw_sincos(SHADER_OPCODE_ARG* arg) { /* This instruction exists in ARB, but the d3d instruction takes two extra parameters which - * must contain fixed constants. So we need a separate functin to filter those constants and + * must contain fixed constants. So we need a separate function to filter those constants and * can't use map2gl */ SHADER_BUFFER* buffer = arg->buffer; @@ -1563,10 +1721,10 @@ void shader_hw_sincos(SHADER_OPCODE_ARG* arg) { DWORD shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; BOOL sat = (arg->dst & WINED3DSP_DSTMOD_MASK) & WINED3DSPDM_SATURATE; - pshader_get_register_name(arg->dst, dst_name); + pshader_get_register_name(arg->shader, arg->dst, dst_name); shader_arb_get_write_mask(arg, arg->dst, dst_wmask); - pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name); + pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_name); shader_addline(buffer, "SCS%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name); @@ -1590,15 +1748,30 @@ void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) { unsigned int i; if ((curOpcode->opcode == WINED3DSIO_MOV && dst_regtype == WINED3DSPR_ADDR) || curOpcode->opcode == WINED3DSIO_MOVA) { + memset(tmpLine, 0, sizeof(tmpLine)); if(shader->rel_offset) { - memset(tmpLine, 0, sizeof(tmpLine)); vshader_program_add_param(arg, src[0], TRUE, tmpLine); shader_addline(buffer, "ADD TMP.x, %s, helper_const.z;\n", tmpLine); shader_addline(buffer, "ARL A0.x, TMP.x;\n"); - return; } else { - strcpy(tmpLine, "ARL"); + /* Apple's ARB_vertex_program implementation does not accept an ARL source argument + * with more than one component. Thus replicate the first source argument over all + * 4 components. For example, .xyzw -> .x (or better: .xxxx), .zwxy -> .z, etc) + */ + DWORD parm = src[0] & ~(WINED3DVS_SWIZZLE_MASK); + if((src[0] & WINED3DVS_X_W) == WINED3DVS_X_W) { + parm |= WINED3DVS_X_W | WINED3DVS_Y_W | WINED3DVS_Z_W | WINED3DVS_W_W; + } else if((src[0] & WINED3DVS_X_Z) == WINED3DVS_X_Z) { + parm |= WINED3DVS_X_Z | WINED3DVS_Y_Z | WINED3DVS_Z_Z | WINED3DVS_W_Z; + } else if((src[0] & WINED3DVS_X_Y) == WINED3DVS_X_Y) { + parm |= WINED3DVS_X_Y | WINED3DVS_Y_Y | WINED3DVS_Z_Y | WINED3DVS_W_Y; + } else if((src[0] & WINED3DVS_X_X) == WINED3DVS_X_X) { + parm |= WINED3DVS_X_X | WINED3DVS_Y_X | WINED3DVS_Z_X | WINED3DVS_W_X; + } + vshader_program_add_param(arg, parm, TRUE, tmpLine); + shader_addline(buffer, "ARL A0.x, %s;\n", tmpLine); } + return; } else strcpy(tmpLine, curOpcode->glname); @@ -1662,22 +1835,24 @@ static GLuint create_arb_blt_fragment_program(WineD3D_GL_Info *gl_info) { static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; if (useVS) { TRACE("Using vertex shader\n"); + priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId; + /* Bind the vertex program */ - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, - ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId)); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);"); /* Enable OpenGL vertex programs */ glEnable(GL_VERTEX_PROGRAM_ARB); checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); - TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", - This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId); + TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id); } else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) { + priv->current_vprogram_id = 0; glDisable(GL_VERTEX_PROGRAM_ARB); checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); } @@ -1685,37 +1860,76 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { if (usePS) { TRACE("Using pixel shader\n"); + priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId; + /* Bind the fragment program */ - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, - ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);"); /* Enable OpenGL fragment programs */ glEnable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);"); - TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", - This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId); - } else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { - glDisable(GL_FRAGMENT_PROGRAM_ARB); - checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id); + } else { + priv->current_fprogram_id = 0; + + if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) { + /* Disable only if we're not using arbfp fixed function fragment processing. If this is used, + * keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function + * replacement shader + */ + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } } } static void shader_arb_select_depth_blt(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - static GLuint vprogram_id = 0; - static GLuint fprogram_id = 0; - if (!vprogram_id) vprogram_id = create_arb_blt_vertex_program(gl_info); - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vprogram_id)); + 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 (!fprogram_id) fprogram_id = create_arb_blt_fragment_program(gl_info); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fprogram_id)); + if (!priv->depth_blt_fprogram_id) priv->depth_blt_fprogram_id = create_arb_blt_fragment_program(gl_info); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->depth_blt_fprogram_id)); glEnable(GL_FRAGMENT_PROGRAM_ARB); } +static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + + if (priv->current_vprogram_id) { + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); + checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);"); + + glEnable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); + + TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id); + } else { + glDisable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); + } + + if (priv->current_fprogram_id) { + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);"); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);"); + + TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id); + } else if(!priv->use_arbfp_fixed_func) { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } +} + static void shader_arb_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -1724,13 +1938,1720 @@ static void shader_arb_cleanup(IWineD3DDevice *iface) { } static void shader_arb_destroy(IWineD3DBaseShader *iface) { + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; + WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *) This->baseShader.device)->adapter->gl_info; + + ENTER_GL(); + GL_EXTCALL(glDeleteProgramsARB(1, &This->baseShader.prgId)); + checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->baseShader.prgId))"); + LEAVE_GL(); + This->baseShader.prgId = 0; + This->baseShader.is_compiled = FALSE; +} + +static HRESULT shader_arb_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv)); + return WINED3D_OK; +} + +static void shader_arb_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; + + if(priv->depth_blt_vprogram_id) { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id)); + } + if(priv->depth_blt_fprogram_id) { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id)); + } + + HeapFree(GetProcessHeap(), 0, This->shader_priv); +} + +static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) { + return TRUE; +} + +static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1, + const char *tmp2, const char *tmp3, const char *tmp4) { + /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ + + /* Calculate the > 0.0031308 case */ + shader_addline(buffer, "POW %s.x, %s.x, srgb_pow.x;\n", tmp1, fragcolor); + shader_addline(buffer, "POW %s.y, %s.y, srgb_pow.y;\n", tmp1, fragcolor); + shader_addline(buffer, "POW %s.z, %s.z, srgb_pow.z;\n", tmp1, fragcolor); + shader_addline(buffer, "MUL %s, %s, srgb_mul_hi;\n", tmp1, tmp1); + shader_addline(buffer, "SUB %s, %s, srgb_sub_hi;\n", tmp1, tmp1); + /* Calculate the < case */ + shader_addline(buffer, "MUL %s, srgb_mul_low, %s;\n", tmp2, fragcolor); + /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */ + shader_addline(buffer, "SLT %s, srgb_comparison, %s;\n", tmp3, fragcolor); + shader_addline(buffer, "SGE %s, srgb_comparison, %s;\n", tmp4, fragcolor); + /* Store the components > 0.0031308 in the destination */ + shader_addline(buffer, "MUL %s, %s, %s;\n", fragcolor, tmp1, tmp3); + /* Add the components that are < 0.0031308 */ + shader_addline(buffer, "MAD result.color.xyz, %s, %s, %s;\n", tmp2, tmp4, fragcolor); + /* [0.0;1.0] clamping. Not needed, this is done implicitly */ +} + +static void shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) { + IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; + shader_reg_maps* reg_maps = &This->baseShader.reg_maps; + CONST DWORD *function = This->baseShader.function; + const char *fragcolor; + WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; + local_constant* lconst; + + /* Create the hw ARB shader */ + shader_addline(buffer, "!!ARBfp1.0\n"); + + shader_addline(buffer, "TEMP TMP;\n"); /* Used in matrix ops */ + shader_addline(buffer, "TEMP TMP2;\n"); /* Used in matrix ops */ + shader_addline(buffer, "TEMP TA;\n"); /* Used for modifiers */ + shader_addline(buffer, "TEMP TB;\n"); /* Used for modifiers */ + shader_addline(buffer, "TEMP TC;\n"); /* Used for modifiers */ + 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"); + + /* Base Declarations */ + shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + + /* We need two variables for fog blending */ + shader_addline(buffer, "TEMP TMP_FOG;\n"); + if (This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)) { + shader_addline(buffer, "TEMP TMP_COLOR;\n"); + } + + /* Base Shader Body */ + shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); + + /* calculate fog and blend it + * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but + * -1/(e-s) and e/(e-s) respectively. + */ + shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n"); + + if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + fragcolor = "R0"; + } else { + fragcolor = "TMP_COLOR"; + } + if(This->srgb_enabled) { + arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB"); + } + if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) { + shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor); + shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor); + } + + shader_addline(buffer, "END\n"); + + /* TODO: change to resource.glObjectHandle or something like that */ + GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId)); + + TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId)); + + TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId); + /* Create the program and check for errors */ + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + buffer->bsize, buffer->buffer)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint errPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); + FIXME("HW PixelShader Error at position %d: %s\n", + errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + This->baseShader.prgId = -1; + } + + /* Load immediate constants */ + if(!This->baseShader.load_local_constsF) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + float *value = (float *) lconst->value; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, lconst->idx, value)); + checkGLcall("glProgramLocalParameter4fvARB"); + } + } +} + +static void shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) { + IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; + shader_reg_maps* reg_maps = &This->baseShader.reg_maps; + CONST DWORD *function = This->baseShader.function; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; + WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + local_constant* lconst; + + /* Create the hw ARB shader */ + shader_addline(buffer, "!!ARBvp1.0\n"); + shader_addline(buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset); + + /* Mesa supports only 95 constants */ + if (GL_VEND(MESA) || GL_VEND(WINE)) + This->baseShader.limits.constant_float = + min(95, This->baseShader.limits.constant_float); + + shader_addline(buffer, "TEMP TMP;\n"); + + /* Base Declarations */ + shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + + /* We need a constant to fixup the final position */ + shader_addline(buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS); + + /* Initialize output parameters. GL_ARB_vertex_program does not require special initialization values + * for output parameters. D3D in theory does not do that either, but some applications depend on a + * proper initialization of the secondary color, and programs using the fixed function pipeline without + * a replacement shader depend on the texcoord.w being set properly. + * + * GL_NV_vertex_program defines that all output values are initialized to {0.0, 0.0, 0.0, 1.0}. This + * assertion is in effect even when using GL_ARB_vertex_program without any NV specific additions. So + * skip this if NV_vertex_program is supported. Otherwise, initialize the secondary color. For the tex- + * coords, we have a flag in the opengl caps. Many cards do not require the texcoord being set, and + * this can eat a number of instructions, so skip it unless this cap is set as well + */ + if(!GL_SUPPORT(NV_VERTEX_PROGRAM)) { + shader_addline(buffer, "MOV result.color.secondary, -helper_const.wwwy;\n"); + + if((GLINFO_LOCATION).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 && + This->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) { + shader_addline(buffer, "MOV result.texcoord[%u].w, -helper_const.y;\n", i); + } + } + } + } + + /* Base Shader Body */ + shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); + + /* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */ + if (!reg_maps->fog) + shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); + + /* Write the final position. + * + * OpenGL coordinates specify the center of the pixel while d3d coords specify + * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains + * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x + * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that. + */ + shader_addline(buffer, "MUL TMP, posFixup, TMP_OUT.w;\n"); + shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TMP.z;\n"); + shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TMP.w;\n"); + + /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c + * and the glsl equivalent + */ + shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); + + shader_addline(buffer, "MOV result.position, TMP_OUT;\n"); + + shader_addline(buffer, "END\n"); + + /* TODO: change to resource.glObjectHandle or something like that */ + GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId)); + + TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId)); + + TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId); + /* Create the program and check for errors */ + GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + buffer->bsize, buffer->buffer)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint errPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); + FIXME("HW VertexShader Error at position %d: %s\n", + errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + This->baseShader.prgId = -1; + } + + /* Load immediate constants */ + if(!This->baseShader.load_local_constsF) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + float *value = (float *) lconst->value; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst->idx, value)); + } + } +} + +static void shader_arb_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) { + /* 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(devtype, gl_info, pCaps); + + if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) { + pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1); + TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n"); + pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF); + } + + if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4); + pCaps->PixelShader1xMaxValue = 8.0; + TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n"); + } +} + +static BOOL shader_arb_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt)); + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_Q8W8V8U8: + case WINED3DFMT_ATI2N: + TRACE("[OK]\n"); + return TRUE; + default: + TRACE("[FAILED\n"); + return FALSE; + } } const shader_backend_t arb_program_shader_backend = { - &shader_arb_select, - &shader_arb_select_depth_blt, - &shader_arb_load_constants, - &shader_arb_cleanup, - &shader_arb_color_correction, - &shader_arb_destroy + shader_arb_select, + shader_arb_select_depth_blt, + shader_arb_deselect_depth_blt, + shader_arb_load_constants, + shader_arb_cleanup, + shader_arb_color_correction, + shader_arb_destroy, + shader_arb_alloc, + shader_arb_free, + shader_arb_dirty_const, + shader_arb_generate_pshader, + shader_arb_generate_vshader, + shader_arb_get_caps, + shader_arb_conv_supported, }; + +/* ARB_fragment_program fixed function pipeline replacement definitions */ +#define ARB_FFP_CONST_TFACTOR 0 +#define ARB_FFP_CONST_SPECULAR_ENABLE ((ARB_FFP_CONST_TFACTOR) + 1) +#define ARB_FFP_CONST_CONSTANT(i) ((ARB_FFP_CONST_SPECULAR_ENABLE) + 1 + i) +#define ARB_FFP_CONST_BUMPMAT(i) ((ARB_FFP_CONST_CONSTANT(7)) + 1 + i) +#define ARB_FFP_CONST_LUMINANCE(i) ((ARB_FFP_CONST_BUMPMAT(7)) + 1 + i) + +struct arbfp_ffp_desc +{ + struct ffp_desc parent; + GLuint shader; + unsigned int num_textures_used; +}; + +static void arbfp_enable(IWineD3DDevice *iface, BOOL enable) { + if(enable) { + glEnable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)"); + } else { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } +} + +static HRESULT arbfp_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct shader_arb_priv *priv; + /* Share private data between the shader backend and the pipeline replacement, if both + * are the arb implementation. This is needed to figure out whether ARBfp should be disabled + * if no pixel shader is bound or not + */ + if(This->shader_backend == &arb_program_shader_backend) { + This->fragment_priv = This->shader_priv; + } else { + This->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv)); + if(!This->fragment_priv) return E_OUTOFMEMORY; + } + priv = (struct shader_arb_priv *) This->fragment_priv; + priv->fragment_shaders = hash_table_create(ffp_program_key_hash, ffp_program_key_compare); + priv->use_arbfp_fixed_func = TRUE; + return WINED3D_OK; +} + +static void arbfp_free_ffpshader(void *value, void *gli) { + WineD3D_GL_Info *gl_info = gli; + struct arbfp_ffp_desc *entry_arb = value; + + ENTER_GL(); + GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader)); + checkGLcall("glDeleteProgramsARB(1, &entry_arb->shader)"); + HeapFree(GetProcessHeap(), 0, entry_arb); + LEAVE_GL(); +} + +static void arbfp_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->fragment_priv; + + hash_table_destroy(priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info); + priv->use_arbfp_fixed_func = FALSE; + + if(This->shader_backend != &arb_program_shader_backend) { + HeapFree(GetProcessHeap(), 0, This->fragment_priv); + } +} + +static void arbfp_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *caps) { + caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | + WINED3DTEXOPCAPS_SELECTARG1 | + WINED3DTEXOPCAPS_SELECTARG2 | + WINED3DTEXOPCAPS_MODULATE4X | + WINED3DTEXOPCAPS_MODULATE2X | + WINED3DTEXOPCAPS_MODULATE | + WINED3DTEXOPCAPS_ADDSIGNED2X | + WINED3DTEXOPCAPS_ADDSIGNED | + WINED3DTEXOPCAPS_ADD | + WINED3DTEXOPCAPS_SUBTRACT | + WINED3DTEXOPCAPS_ADDSMOOTH | + WINED3DTEXOPCAPS_BLENDCURRENTALPHA | + WINED3DTEXOPCAPS_BLENDFACTORALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | + WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM | + WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_DOTPRODUCT3 | + WINED3DTEXOPCAPS_MULTIPLYADD | + WINED3DTEXOPCAPS_LERP | + WINED3DTEXOPCAPS_BUMPENVMAP | + WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE; + + /* TODO: Implement WINED3DTEXOPCAPS_PREMODULATE */ + + caps->MaxTextureBlendStages = 8; + caps->MaxSimultaneousTextures = min(GL_LIMITS(fragment_samplers), 8); + + caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; +} +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float col[4]; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + + /* Do not overwrite pixel shader constants if a pshader is in use */ + if(use_ps(device)) return; + + D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)"); + + if(device->shader_backend == &arb_program_shader_backend) { + device = stateblock->wineD3DDevice; + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1); + } +} + +static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float col[4]; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + + /* Do not overwrite pixel shader constants if a pshader is in use */ + if(use_ps(device)) return; + + if(stateblock->renderState[WINED3DRS_SPECULARENABLE]) { + /* The specular color has no alpha */ + col[0] = 1.0; col[1] = 1.0; + col[2] = 1.0; col[3] = 0.0; + } else { + col[0] = 0.0; col[1] = 0.0; + col[2] = 0.0; col[3] = 0.0; + } + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col)); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col)"); + + if(device->shader_backend == &arb_program_shader_backend) { + device = stateblock->wineD3DDevice; + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_SPECULAR_ENABLE + 1); + } +} + +static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + float mat[2][2]; + + if(use_ps(device)) { + if(stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) { + /* 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); + } + } + /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */ + return; + } + + mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); + mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]); + mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]); + mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]); + + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])"); + + if(device->shader_backend == &arb_program_shader_backend) { + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1); + } +} + +static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + float param[4]; + + if(use_ps(device)) { + if(stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) { + /* 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); + } + } + /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */ + return; + } + + param[0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]); + param[1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]); + param[2] = 0.0; + param[3] = 0.0; + + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param)); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param)"); + + if(device->shader_backend == &arb_program_shader_backend) { + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1); + } +} + +static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int stage, DWORD arg) { + const char *ret; + + if(arg == ARG_UNUSED) return "unused"; /* This is the marker for unused registers */ + + switch(arg & WINED3DTA_SELECTMASK) { + case WINED3DTA_DIFFUSE: + ret = "fragment.color.primary"; break; + + case WINED3DTA_CURRENT: + if(stage == 0) ret = "fragment.color.primary"; + else ret = "ret"; + break; + + case WINED3DTA_TEXTURE: + switch(stage) { + case 0: ret = "tex0"; break; + case 1: ret = "tex1"; break; + case 2: ret = "tex2"; break; + case 3: ret = "tex3"; break; + case 4: ret = "tex4"; break; + case 5: ret = "tex5"; break; + case 6: ret = "tex6"; break; + case 7: ret = "tex7"; break; + default: ret = "unknown texture"; + } + break; + + case WINED3DTA_TFACTOR: + ret = "tfactor"; break; + + case WINED3DTA_SPECULAR: + ret = "fragment.color.secondary"; break; + + case WINED3DTA_TEMP: + ret = "tempreg"; break; + + case WINED3DTA_CONSTANT: + FIXME("Implement perstage constants\n"); + switch(stage) { + case 0: ret = "const0"; break; + case 1: ret = "const1"; break; + case 2: ret = "const2"; break; + case 3: ret = "const3"; break; + case 4: ret = "const4"; break; + case 5: ret = "const5"; break; + case 6: ret = "const6"; break; + case 7: ret = "const7"; break; + } + default: + return "unknown"; + } + + if(arg & WINED3DTA_COMPLEMENT) { + shader_addline(buffer, "SUB arg%u, const.x, %s;\n", argnum, ret); + if(argnum == 0) ret = "arg0"; + if(argnum == 1) ret = "arg1"; + if(argnum == 2) ret = "arg2"; + } + if(arg & WINED3DTA_ALPHAREPLICATE) { + shader_addline(buffer, "MOV arg%u, %s.a;\n", argnum, ret); + if(argnum == 0) ret = "arg0"; + if(argnum == 1) ret = "arg1"; + if(argnum == 2) ret = "arg2"; + } + return ret; +} + +static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color, BOOL alpha, + DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) { + const char *dstmask, *dstreg, *arg0, *arg1, *arg2; + unsigned int mul = 1; + BOOL mul_final_dest = FALSE; + + if(color && alpha) dstmask = ""; + else if(color) dstmask = ".rgb"; + else dstmask = ".a"; + + if(dst == tempreg) dstreg = "tempreg"; + else dstreg = "ret"; + + arg0 = get_argreg(buffer, 0, stage, dw_arg0); + arg1 = get_argreg(buffer, 1, stage, dw_arg1); + arg2 = get_argreg(buffer, 2, stage, dw_arg2); + + switch(op) { + case WINED3DTOP_DISABLE: + if(stage == 1) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask); + break; + + case WINED3DTOP_SELECTARG2: + arg1 = arg2; + case WINED3DTOP_SELECTARG1: + shader_addline(buffer, "MOV %s%s, %s;\n", dstreg, dstmask, arg1); + break; + + case WINED3DTOP_MODULATE4X: + mul = 2; + case WINED3DTOP_MODULATE2X: + mul *= 2; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + case WINED3DTOP_MODULATE: + shader_addline(buffer, "MUL %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_ADDSIGNED2X: + mul = 2; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + case WINED3DTOP_ADDSIGNED: + shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2); + arg2 = "arg2"; + case WINED3DTOP_ADD: + shader_addline(buffer, "ADD_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_SUBTRACT: + shader_addline(buffer, "SUB_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_ADDSMOOTH: + shader_addline(buffer, "SUB arg1, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD_SAT %s%s, arg1, %s, %s;\n", dstreg, dstmask, arg2, arg1); + break; + + case WINED3DTOP_BLENDCURRENTALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDFACTORALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDDIFFUSEALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + + case WINED3DTOP_BLENDTEXTUREALPHAPM: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE); + shader_addline(buffer, "SUB arg0.a, const.x, %s.a;\n", arg0); + shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.a, %s;\n", dstreg, dstmask, arg2, arg1); + break; + + /* D3DTOP_PREMODULATE ???? */ + + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD_SAT %s%s, arg0.a, %s, %s;\n", dstreg, dstmask, arg2, arg1); + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + shader_addline(buffer, "MAD_SAT %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1); + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.a;\n", dstreg, dstmask, arg2, arg1); + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.a;\n", dstreg, dstmask, arg1, arg2, arg1); + break; + + case WINED3DTOP_DOTPRODUCT3: + mul = 4; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + shader_addline(buffer, "SUB arg1, %s, const.w;\n", arg1); + shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2); + shader_addline(buffer, "DP3_SAT %s%s, arg1, arg2;\n", dstreg, dstmask); + break; + + case WINED3DTOP_MULTIPLYADD: + shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg0); + break; + + case WINED3DTOP_LERP: + /* The msdn is not quite right here */ + shader_addline(buffer, "LRP %s%s, %s, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + + case WINED3DTOP_BUMPENVMAP: + case WINED3DTOP_BUMPENVMAPLUMINANCE: + /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */ + break; + + default: + FIXME("Unhandled texture op %08x\n", op); + } + + if(mul == 2) { + shader_addline(buffer, "MUL_SAT %s%s, %s, const.y;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg); + } else if(mul == 4) { + shader_addline(buffer, "MUL_SAT %s%s, %s, const.z;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg); + } +} + +/* The stateblock is passed for GLINFO_LOCATION */ +static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateBlockImpl *stateblock) { + unsigned int stage; + SHADER_BUFFER buffer; + BOOL tex_read[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; + BOOL bump_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; + BOOL luminance_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; + const char *textype; + const char *instr, *sat; + char colorcor_dst[8]; + GLuint ret; + DWORD arg0, arg1, arg2; + BOOL tempreg_used = FALSE, tfactor_used = FALSE; + BOOL op_equal; + const char *final_combiner_src = "ret"; + + /* Find out which textures are read */ + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(settings->op[stage].cop == WINED3DTOP_DISABLE) break; + arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK; + if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + + if(settings->op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) tex_read[stage] = TRUE; + if(settings->op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHAPM) tex_read[stage] = TRUE; + if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAP) { + bump_used[stage] = TRUE; + tex_read[stage] = TRUE; + } + if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) { + bump_used[stage] = TRUE; + tex_read[stage] = TRUE; + luminance_used[stage] = TRUE; + } else if(settings->op[stage].cop == WINED3DTOP_BLENDFACTORALPHA) { + tfactor_used = TRUE; + } + + if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) { + tfactor_used = TRUE; + } + + if(settings->op[stage].dst == tempreg) tempreg_used = TRUE; + if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) { + tempreg_used = TRUE; + } + + if(settings->op[stage].aop == WINED3DTOP_DISABLE) continue; + arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK; + if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + + if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) { + tempreg_used = TRUE; + } + if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) { + tfactor_used = TRUE; + } + } + + /* Shader header */ + buffer.bsize = 0; + buffer.lineNo = 0; + buffer.newline = TRUE; + buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); + + shader_addline(&buffer, "!!ARBfp1.0\n"); + + switch(settings->fog) { + case FOG_OFF: break; + case FOG_LINEAR: shader_addline(&buffer, "OPTION ARB_fog_linear;\n"); break; + case FOG_EXP: shader_addline(&buffer, "OPTION ARB_fog_exp;\n"); break; + case FOG_EXP2: shader_addline(&buffer, "OPTION ARB_fog_exp2;\n"); break; + default: FIXME("Unexpected fog setting %d\n", settings->fog); + } + + shader_addline(&buffer, "PARAM const = {1, 2, 4, 0.5};\n"); + shader_addline(&buffer, "TEMP ret;\n"); + if(tempreg_used || settings->sRGB_write) shader_addline(&buffer, "TEMP tempreg;\n"); + shader_addline(&buffer, "TEMP arg0;\n"); + shader_addline(&buffer, "TEMP arg1;\n"); + shader_addline(&buffer, "TEMP arg2;\n"); + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(!tex_read[stage]) continue; + shader_addline(&buffer, "TEMP tex%u;\n", stage); + if(!bump_used[stage]) continue; + shader_addline(&buffer, "PARAM bumpmat%u = program.env[%u];\n", stage, ARB_FFP_CONST_BUMPMAT(stage)); + if(!luminance_used[stage]) continue; + shader_addline(&buffer, "PARAM luminance%u = program.env[%u];\n", stage, ARB_FFP_CONST_LUMINANCE(stage)); + } + if(tfactor_used) { + shader_addline(&buffer, "PARAM tfactor = program.env[%u];\n", ARB_FFP_CONST_TFACTOR); + } + shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE); + + if(settings->sRGB_write) { + shader_addline(&buffer, "PARAM srgb_mul_low = {%f, %f, %f, 1.0};\n", + srgb_mul_low, srgb_mul_low, srgb_mul_low); + shader_addline(&buffer, "PARAM srgb_comparison = {%f, %f, %f, %f};\n", + srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp); + shader_addline(&buffer, "PARAM srgb_pow = {%f, %f, %f, 1.0};\n", + srgb_pow, srgb_pow, srgb_pow); + shader_addline(&buffer, "PARAM srgb_mul_hi = {%f, %f, %f, 1.0};\n", + srgb_mul_high, srgb_mul_high, srgb_mul_high); + shader_addline(&buffer, "PARAM srgb_sub_hi = {%f, %f, %f, 0.0};\n", + srgb_sub_high, srgb_sub_high, srgb_sub_high); + } + + /* Generate texture sampling instructions) */ + for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) { + if(!tex_read[stage]) continue; + + switch(settings->op[stage].tex_type) { + case tex_1d: textype = "1D"; break; + case tex_2d: textype = "2D"; break; + case tex_3d: textype = "3D"; break; + case tex_cube: textype = "CUBE"; break; + case tex_rect: textype = "RECT"; break; + default: textype = "unexpected_textype"; break; + } + + if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAP || + settings->op[stage].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) { + sat = ""; + } else { + sat = "_SAT"; + } + + if(settings->op[stage].projected == proj_none) { + instr = "TEX"; + } else if(settings->op[stage].projected == proj_count4 || + settings->op[stage].projected == proj_count3) { + instr = "TXP"; + } else { + FIXME("Unexpected projection mode %d\n", settings->op[stage].projected); + instr = "TXP"; + } + + if(stage > 0 && + (settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP || + settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) { + shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1); + shader_addline(&buffer, "DP3 ret.r, arg1, tex%u;\n", stage - 1); + shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1); + shader_addline(&buffer, "DP3 ret.g, arg1, tex%u;\n", stage - 1); + + /* with projective textures, texbem only divides the static texture coord, not the displacement, + * so multiply the displacement with the dividing parameter before passing it to TXP + */ + if (settings->op[stage].projected != proj_none) { + if(settings->op[stage].projected == proj_count4) { + shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].a;\n", stage); + shader_addline(&buffer, "MUL ret.rgb, ret, fragment.texcoord[%u].a, fragment.texcoord[%u];\n", stage, stage); + } else { + shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].b;\n", stage); + shader_addline(&buffer, "MAD ret.rgb, ret, fragment.texcoord[%u].b, fragment.texcoord[%u];\n", stage, stage); + } + } else { + shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage); + } + + shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n", + instr, sat, stage, stage, textype); + if(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) { + shader_addline(&buffer, "MAD_SAT ret.r, tex%u.b, luminance%u.r, luminance%u.g;\n", + stage - 1, stage - 1, stage - 1); + shader_addline(&buffer, "MUL tex%u, tex%u, ret.r;\n", stage, stage); + } + } else if(settings->op[stage].projected == proj_count3) { + shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage); + shader_addline(&buffer, "MOV ret.a, ret.b;\n"); + shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n", + instr, sat, stage, stage, textype); + } else { + shader_addline(&buffer, "%s%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n", + instr, sat, stage, stage, stage, textype); + } + + sprintf(colorcor_dst, "tex%u", stage); + gen_color_correction(&buffer, colorcor_dst, ".rgba", "const.x", "const.y", + settings->op[stage].color_correction, &GLINFO_LOCATION); + } + + /* Generate the main shader */ + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(settings->op[stage].cop == WINED3DTOP_DISABLE) { + if(stage == 0) { + final_combiner_src = "fragment.color.primary"; + } + break; + } + + if(settings->op[stage].cop == WINED3DTOP_SELECTARG1 && + settings->op[stage].aop == WINED3DTOP_SELECTARG1) { + op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1; + } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG1 && + settings->op[stage].aop == WINED3DTOP_SELECTARG2) { + op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2; + } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG2 && + settings->op[stage].aop == WINED3DTOP_SELECTARG1) { + op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1; + } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG2 && + settings->op[stage].aop == WINED3DTOP_SELECTARG2) { + op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2; + } else { + op_equal = settings->op[stage].aop == settings->op[stage].cop && + settings->op[stage].carg0 == settings->op[stage].aarg0 && + settings->op[stage].carg1 == settings->op[stage].aarg1 && + settings->op[stage].carg2 == settings->op[stage].aarg2; + } + + if(settings->op[stage].aop == WINED3DTOP_DISABLE) { + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + if(stage == 0) { + shader_addline(&buffer, "MOV ret.a, fragment.color.primary.a;\n"); + } + } else if(op_equal) { + gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + } else { + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst, + settings->op[stage].aop, settings->op[stage].aarg0, + settings->op[stage].aarg1, settings->op[stage].aarg2); + } + } + + if(settings->sRGB_write) { + shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src); + arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg"); + shader_addline(&buffer, "MOV result.color.a, ret.a;\n"); + } else { + shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src); + } + + /* Footer */ + shader_addline(&buffer, "END\n"); + + /* Generate the shader */ + GL_EXTCALL(glGenProgramsARB(1, &ret)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret)); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(buffer.buffer), buffer.buffer)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint pos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + FIXME("Fragment program error at position %d: %s\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + } + HeapFree(GetProcessHeap(), 0, buffer.buffer); + return ret; +} + +static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + struct shader_arb_priv *priv = (struct shader_arb_priv *) device->fragment_priv; + BOOL use_pshader = use_ps(device); + BOOL use_vshader = use_vs(device); + struct ffp_settings settings; + struct arbfp_ffp_desc *desc; + unsigned int i; + + if(isStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE))) { + if(use_pshader) { + IWineD3DPixelShader_CompileShader(stateblock->pixelShader); + } else if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) { + /* Reload fixed function constants since they collide with the pixel shader constants */ + for(i = 0; i < MAX_TEXTURES; i++) { + set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context); + } + state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context); + state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context); + } + return; + } + + if(use_pshader) { + IWineD3DPixelShader_CompileShader(stateblock->pixelShader); + } else { + /* Find or create a shader implementing the fixed function pipeline settings, then activate it */ + gen_ffp_op(stateblock, &settings, FALSE); + desc = (struct arbfp_ffp_desc *) find_ffp_shader(priv->fragment_shaders, &settings); + if(!desc) { + desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc)); + if(!desc) { + ERR("Out of memory\n"); + return; + } + desc->num_textures_used = 0; + for(i = 0; i < GL_LIMITS(texture_stages); i++) { + if(settings.op[i].cop == WINED3DTOP_DISABLE) break; + desc->num_textures_used = i; + } + + memcpy(&desc->parent.settings, &settings, sizeof(settings)); + desc->shader = gen_arbfp_ffp_shader(&settings, stateblock); + add_ffp_shader(priv->fragment_shaders, &desc->parent); + TRACE("Allocated fixed function replacement shader descriptor %p\n", desc); + } + + /* Now activate the replacement program. GL_FRAGMENT_PROGRAM_ARB is already active(however, note the + * comment above the shader_select call below). If e.g. GLSL is active, the shader_select call will + * deactivate it. + */ + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)"); + + if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) { + /* Reload fixed function constants since they collide with the pixel shader constants */ + for(i = 0; i < MAX_TEXTURES; i++) { + set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context); + } + state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context); + state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context); + } + } + + /* Finally, select the shader. If a pixel shader is used, it will be set and enabled by the shader backend. + * If this shader backend is arbfp(most likely), then it will simply overwrite the last fixed function replace- + * ment shader. If the shader backend is not ARB, it currently is important that the opengl implementation + * type overwrites GL_ARB_fragment_program. This is currently the case with GLSL. If we really want to use + * atifs or nvrc pixel shaders with arb fragment programs we'd have to disable GL_FRAGMENT_PROGRAM_ARB here + * + * Don't call shader_select if the vertex shader is dirty, because some shader backends(GLSL) need both shaders + * to be compiled before activating them(needs some cleanups in the shader backend interface) + */ + if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { + device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, 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); + } +} + +/* We can't link the fog states to the fragment state directly since the vertex pipeline links them + * to FOGENABLE. A different linking in different pipeline parts can't be expressed in the combined + * state table, so we need to handle that with a forwarding function. The other invisible side effect + * is that changing the fog start and fog end(which links to FOGENABLE in vertex) results in the + * fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here + */ +static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(!isStateDirty(context, STATE_PIXELSHADER)) { + fragment_prog_arbfp(state, stateblock, context); + } +} + +static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(!isStateDirty(context, STATE_PIXELSHADER)) { + fragment_prog_arbfp(state, stateblock, context); + } +} + +#undef GLINFO_LOCATION + +static const struct StateEntryTemplate arbfp_fragmentstate_template[] = { + {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_arb_specularenable}, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; + +const struct fragment_pipeline arbfp_fragment_pipeline = { + arbfp_enable, + arbfp_get_caps, + arbfp_alloc, + arbfp_free, + shader_arb_conv_supported, + arbfp_fragmentstate_template, + 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; +}; + +static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv)); + if(!device->blit_priv) { + ERR("Out of memory\n"); + return E_OUTOFMEMORY; + } + return WINED3D_OK; +} +static void arbfp_blit_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv; + + ENTER_GL(); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_rect_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_rect_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader)); + checkGLcall("Delete yuv programs\n"); + LEAVE_GL(); +} + +static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, WINED3DFORMAT fmt, GLenum textype, char *luminance) { + char chroma; + const char *tex, *texinstr; + + if(fmt == WINED3DFMT_UYVY) { + chroma = 'r'; + *luminance = 'a'; + } else { + chroma = 'a'; + *luminance = 'r'; + } + switch(textype) { + case GL_TEXTURE_2D: tex = "2D"; texinstr = "TXP"; break; + case GL_TEXTURE_RECTANGLE_ARB: tex = "RECT"; texinstr = "TEX"; break; + default: + /* This is more tricky than just replacing the texture type - we have to navigate + * properly in the texture to find the correct chroma values + */ + FIXME("Implement yuv correction for non-2d, non-rect textures\n"); + return FALSE; + } + + /* First we have to read the chroma values. This means we need at least two pixels(no filtering), + * or 4 pixels(with filtering). To get the unmodified chromas, we have to rid ourselves of the + * filtering when we sample the texture. + * + * These are the rules for reading the chroma: + * + * Even pixel: Cr + * Even pixel: U + * Odd pixel: V + * + * So we have to get the sampling x position in non-normalized coordinates in integers + */ + if(textype != GL_TEXTURE_RECTANGLE_ARB) { + shader_addline(buffer, "MUL texcrd.rg, fragment.texcoord[0], size.x;\n"); + shader_addline(buffer, "MOV texcrd.a, size.x;\n"); + } else { + shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n"); + } + /* We must not allow filtering between pixel x and x+1, this would mix U and V + * Vertical filtering is ok. However, bear in mind that the pixel center is at + * 0.5, so add 0.5. + */ + shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n"); + shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n"); + + /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for the + * even and odd pixels respectively + */ + shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n"); + shader_addline(buffer, "FRC texcrd2, texcrd2;\n"); + + /* Sample Pixel 1 */ + shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex); + + /* Put the value into either of the chroma values */ + shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MUL chroma.r, luminance.%c, temp.x;\n", chroma); + shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MUL chroma.g, luminance.%c, temp.x;\n", chroma); + + /* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample + * the pixel right to the current one. Otherwise, sample the left pixel. + * Bias and scale the SLT result to -1;1 and add it to the texcrd.x. + */ + shader_addline(buffer, "MAD temp.x, temp.x, coef.z, -coef.x;\n"); + shader_addline(buffer, "ADD texcrd.x, texcrd, temp.x;\n"); + shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex); + + /* Put the value into the other chroma */ + shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MAD chroma.g, luminance.%c, temp.x, chroma.g;\n", chroma); + shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MAD chroma.r, luminance.%c, temp.x, chroma.r;\n", chroma); + + /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of + * the current one and lerp the two U and V values + */ + + /* This gives the correctly filtered luminance value */ + shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex); + + return TRUE; +} + +static BOOL gen_yv12_read(SHADER_BUFFER *buffer, WINED3DFORMAT fmt, GLenum textype, char *luminance) { + const char *tex; + + switch(textype) { + case GL_TEXTURE_2D: tex = "2D"; break; + case GL_TEXTURE_RECTANGLE_ARB: tex = "RECT"; break; + default: + FIXME("Implement yv12 correction for non-2d, non-rect textures\n"); + return FALSE; + } + + /* YV12 surfaces contain a WxH sized luminance plane, followed by a (W/2)x(H/2) + * V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So the effective + * bitdepth is 12 bits per pixel. Since the U and V planes have only half the + * pitch of the luminance plane, the packing into the gl texture is a bit + * unfortunate. If the whole texture is interpreted as luminance data it looks + * approximately like this: + * + * +----------------------------------+---- + * | | + * | | + * | | + * | | + * | | 2 + * | LUMINANCE | - + * | | 3 + * | | + * | | + * | | + * | | + * +----------------+-----------------+---- + * | | | + * | U even rows | U odd rows | + * | | | 1 + * +----------------+------------------ - + * | | | 3 + * | V even rows | V odd rows | + * | | | + * +----------------+-----------------+---- + * | | | + * | 0.5 | 0.5 | + * + * So it appears as if there are 4 chroma images, but in fact the odd rows + * in the chroma images are in the same row as the even ones. So its is + * kinda tricky to read + * + * When reading from rectangle textures, keep in mind that the input y coordinates + * go from 0 to d3d_height, whereas the opengl texture height is 1.5 * d3d_height + */ + shader_addline(buffer, "PARAM yv12_coef = {%f, %f, %f, %f};\n", + 2.0 / 3.0, 1.0 / 6.0, (2.0 / 3.0) + (1.0 / 6.0), 1.0 / 3.0); + + shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n"); + /* the chroma planes have only half the width */ + shader_addline(buffer, "MUL texcrd.x, texcrd.x, coef.y;\n"); + + /* The first value is between 2/3 and 5/6th of the texture's height, so scale+bias + * the coordinate. Also read the right side of the image when reading odd lines + * + * Don't forget to clamp the y values in into the range, otherwise we'll get filtering + * bleeding + */ + if(textype == GL_TEXTURE_2D) { + + shader_addline(buffer, "RCP chroma.w, size.y;\n"); + + shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n"); + + shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n"); + shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, yv12_coef.x;\n"); + + /* Read odd lines from the right side(add size * 0.5 to the x coordinate */ + shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */ + shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n"); + shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n"); + + /* clamp, keep the half pixel origin in mind */ + shader_addline(buffer, "MAD temp.y, coef.y, chroma.w, yv12_coef.x;\n"); + shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n"); + shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.z;\n"); + shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n"); + } else { + /* Read from [size - size+size/4] */ + shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n"); + shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n"); + + /* Read odd lines from the right side(add size * 0.5 to the x coordinate */ + shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */ + shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n"); + shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n"); + shader_addline(buffer, "MUL texcrd2.x, texcrd2.x, size.x;\n"); + shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n"); + + /* Make sure to read exactly from the pixel center */ + shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n"); + shader_addline(buffer, "ADD texcrd.y, texcrd.y, coef.y;\n"); + + /* Clamp */ + shader_addline(buffer, "MAD temp.y, size.y, coef.w, size.y;\n"); + shader_addline(buffer, "ADD temp.y, temp.y, -coef.y;\n"); + shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n"); + shader_addline(buffer, "ADD temp.y, size.y, -coef.y;\n"); + shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n"); + } + /* Read the texture, put the result into the output register */ + shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex); + shader_addline(buffer, "MOV chroma.r, temp.a;\n"); + + /* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th + * No need to clamp because we're just reusing the already clamped value from above + */ + if(textype == GL_TEXTURE_2D) { + shader_addline(buffer, "ADD texcrd.y, texcrd.y, yv12_coef.y;\n"); + } else { + shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n"); + } + shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex); + shader_addline(buffer, "MOV chroma.g, temp.a;\n"); + + /* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate. + * Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance + * values due to filtering + */ + shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n"); + if(textype == GL_TEXTURE_2D) { + /* Multiply the y coordinate by 2/3 and clamp it */ + shader_addline(buffer, "MUL texcrd.y, texcrd.y, yv12_coef.x;\n"); + shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.x;\n"); + shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n"); + shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); + } else { + /* Reading from texture_rectangles is pretty streightforward, just use the unmodified + * texture coordinate. It is still a good idea to clamp it though, since the opengl texture + * is bigger + */ + shader_addline(buffer, "ADD temp.x, size.y, -coef.y;\n"); + shader_addline(buffer, "MIN texcrd.y, texcrd.y, size.x;\n"); + shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); + } + *luminance = 'a'; + + return TRUE; +} + +static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, WINED3DFORMAT fmt, GLenum textype) { + GLenum shader; + SHADER_BUFFER buffer; + char luminance_component; + struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv; + + /* Shader header */ + buffer.bsize = 0; + buffer.lineNo = 0; + buffer.newline = TRUE; + buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); + + GL_EXTCALL(glGenProgramsARB(1, &shader)); + checkGLcall("GL_EXTCALL(glGenProgramsARB(1, &shader))"); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)"); + if(!shader) { + HeapFree(GetProcessHeap(), 0, buffer.buffer); + return 0; + } + + /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit macropixel, + * giving effectively 16 bit per pixel. The color consists of a luminance(Y) and + * two chroma(U and V) values. Each macropixel has two luminance values, one for + * each single pixel it contains, and one U and one V value shared between both + * pixels. + * + * The data is loaded into an A8L8 texture. With YUY2, the luminance component + * contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus + * take the format into account when generating the read swizzles + * + * Reading the Y value is streightforward - just sample the texture. The hardware + * takes care of filtering in the horizontal and vertical direction. + * + * Reading the U and V values is harder. We have to avoid filtering horizontally, + * because that would mix the U and V values of one pixel or two adjacent pixels. + * Thus floor the texture coordinate and add 0.5 to get an unfiltered read, + * regardless of the filtering setting. Vertical filtering works automatically + * though - the U and V values of two rows are mixed nicely. + * + * Appart of avoiding filtering issues, the code has to know which value it just + * read, and where it can find the other one. To determine this, it checks if + * it sampled an even or odd pixel, and shifts the 2nd read accordingly. + * + * Handling horizontal filtering of U and V values requires reading a 2nd pair + * of pixels, extracting U and V and mixing them. This is not implemented yet. + * + * An alternative implementation idea is to load the texture as A8R8G8B8 texture, + * with width / 2. This way one read gives all 3 values, finding U and V is easy + * in an unfiltered situation. Finding the luminance on the other hand requires + * finding out if it is an odd or even pixel. The real drawback of this approach + * is filtering. This would have to be emulated completely in the shader, reading + * up two 2 packed pixels in up to 2 rows and interpolating both horizontally and + * vertically. Beyond that it would require adjustments to the texture handling + * code to deal with the width scaling + */ + shader_addline(&buffer, "!!ARBfp1.0\n"); + shader_addline(&buffer, "TEMP luminance;\n"); + shader_addline(&buffer, "TEMP temp;\n"); + shader_addline(&buffer, "TEMP chroma;\n"); + shader_addline(&buffer, "TEMP texcrd;\n"); + shader_addline(&buffer, "TEMP texcrd2;\n"); + shader_addline(&buffer, "PARAM coef = {1.0, 0.5, 2.0, 0.25};\n"); + shader_addline(&buffer, "PARAM yuv_coef = {1.403, 0.344, 0.714, 1.770};\n"); + shader_addline(&buffer, "PARAM size = program.local[0];\n"); + + if(fmt == WINED3DFMT_UYVY || fmt ==WINED3DFMT_YUY2) { + if(gen_planar_yuv_read(&buffer, fmt, textype, &luminance_component) == FALSE) { + HeapFree(GetProcessHeap(), 0, buffer.buffer); + return 0; + } + } else { + if(gen_yv12_read(&buffer, fmt, textype, &luminance_component) == FALSE) { + HeapFree(GetProcessHeap(), 0, buffer.buffer); + return 0; + } + } + + /* Calculate the final result. Formula is taken from + * http://www.fourcc.org/fccyvrgb.php. Note that the chroma + * ranges from -0.5 to 0.5 + */ + shader_addline(&buffer, "SUB chroma.rg, chroma, coef.y;\n"); + + shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, luminance.%c;\n", luminance_component); + shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, luminance.%c;\n", luminance_component); + shader_addline(&buffer, "MAD result.color.g, -chroma.r, yuv_coef.z, temp.r;\n"); + shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, luminance.%c;\n", luminance_component); + shader_addline(&buffer, "END\n"); + + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(buffer.buffer), buffer.buffer)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint pos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + FIXME("Fragment program error at position %d: %s\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + } + HeapFree(GetProcessHeap(), 0, buffer.buffer); + + if(fmt == WINED3DFMT_YUY2) { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + priv->yuy2_rect_shader = shader; + } else { + priv->yuy2_2d_shader = shader; + } + } else if(fmt == WINED3DFMT_UYVY) { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + priv->uyvy_rect_shader = shader; + } else { + priv->uyvy_2d_shader = shader; + } + } else { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + priv->yv12_rect_shader = shader; + } else { + priv->yv12_2d_shader = shader; + } + } + return shader; +} + +static HRESULT arbfp_blit_set(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height) { + GLenum shader; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + float size[4] = {width, height, 1, 1}; + struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv; + const GlPixelFormatDesc *glDesc; + + getFormatDescEntry(fmt, &GLINFO_LOCATION, &glDesc); + + if(glDesc->conversion_group != WINED3DFMT_YUY2 && glDesc->conversion_group != WINED3DFMT_UYVY && + glDesc->conversion_group != WINED3DFMT_YV12) { + TRACE("Format: %s\n", debug_d3dformat(glDesc->conversion_group)); + /* Don't bother setting up a shader for unconverted formats */ + glEnable(textype); + checkGLcall("glEnable(textype)"); + return WINED3D_OK; + } + + if(glDesc->conversion_group == WINED3DFMT_YUY2) { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + shader = priv->yuy2_rect_shader; + } else { + shader = priv->yuy2_2d_shader; + } + } else if(glDesc->conversion_group == WINED3DFMT_UYVY) { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + shader = priv->uyvy_rect_shader; + } else { + shader = priv->uyvy_2d_shader; + } + } else { + if(textype == GL_TEXTURE_RECTANGLE_ARB) { + shader = priv->yv12_rect_shader; + } else { + shader = priv->yv12_2d_shader; + } + } + + if(!shader) { + shader = gen_yuv_shader(device, glDesc->conversion_group, textype); + } + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)"); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)"); + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, size)); + checkGLcall("glProgramLocalParameter4fvARB"); + + return WINED3D_OK; +} + +static void arbfp_blit_unset(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } +} + +static BOOL arbfp_blit_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking blit format support for format %s:", debug_d3dformat(fmt)); + switch(fmt) { + case WINED3DFMT_YUY2: + case WINED3DFMT_UYVY: + case WINED3DFMT_YV12: + TRACE("[OK]\n"); + return TRUE; + default: + TRACE("[FAILED]\n"); + return FALSE; + } +} + +const struct blit_shader arbfp_blit = { + arbfp_blit_alloc, + arbfp_blit_free, + arbfp_blit_set, + arbfp_blit_unset, + arbfp_blit_conv_supported +}; + +#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 new file mode 100644 index 00000000000..20c4ebef495 --- /dev/null +++ b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -0,0 +1,1121 @@ +/* + * Fixed function pipeline replacement using GL_ATI_fragment_shader + * + * Copyright 2008 Stefan Dösinger(for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); + +/* Some private defines, Constant associations, etc. + * Env bump matrix and per stage constant should be independent, + * a stage that bump maps can't read the per state constant + */ +#define ATI_FFP_CONST_BUMPMAT(i) (GL_CON_0_ATI + i) +#define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI +#define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI +#define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI +#define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI +#define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI +#define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI +#define ATI_FFP_CONST_TFACTOR GL_CON_6_ATI + +/* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */ +struct atifs_ffp_desc +{ + struct ffp_desc parent; + GLuint shader; + unsigned int num_textures_used; +}; + +struct atifs_private_data +{ + struct hash_table_t *fragment_shaders; /* A hashtable to track fragment pipeline replacement shaders */ + +}; + +static const char *debug_dstmod(GLuint mod) { + switch(mod) { + case GL_NONE: return "GL_NONE"; + case GL_2X_BIT_ATI: return "GL_2X_BIT_ATI"; + case GL_4X_BIT_ATI: return "GL_4X_BIT_ATI"; + case GL_8X_BIT_ATI: return "GL_8X_BIT_ATI"; + case GL_HALF_BIT_ATI: return "GL_HALF_BIT_ATI"; + case GL_QUARTER_BIT_ATI: return "GL_QUARTER_BIT_ATI"; + case GL_EIGHTH_BIT_ATI: return "GL_EIGHTH_BIT_ATI"; + case GL_SATURATE_BIT_ATI: return "GL_SATURATE_BIT_ATI"; + default: return "Unexpected modifier\n"; + } +} + +static const char *debug_argmod(GLuint mod) { + switch(mod) { + case GL_NONE: + return "GL_NONE"; + + case GL_2X_BIT_ATI: + return "GL_2X_BIT_ATI"; + case GL_COMP_BIT_ATI: + return "GL_COMP_BIT_ATI"; + case GL_NEGATE_BIT_ATI: + return "GL_NEGATE_BIT_ATI"; + case GL_BIAS_BIT_ATI: + return "GL_BIAS_BIT_ATI"; + + case GL_2X_BIT_ATI | GL_COMP_BIT_ATI: + return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI"; + case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI: + return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI"; + case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI"; + case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI: + return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI"; + case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI"; + case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; + + case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; + case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; + case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI"; + case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI: + return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI"; + + case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: + return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; + + default: + return "Unexpected argmod combination\n"; + } +} +static const char *debug_register(GLuint reg) { + switch(reg) { + case GL_REG_0_ATI: return "GL_REG_0_ATI"; + case GL_REG_1_ATI: return "GL_REG_1_ATI"; + case GL_REG_2_ATI: return "GL_REG_2_ATI"; + case GL_REG_3_ATI: return "GL_REG_3_ATI"; + case GL_REG_4_ATI: return "GL_REG_4_ATI"; + case GL_REG_5_ATI: return "GL_REG_5_ATI"; + + case GL_CON_0_ATI: return "GL_CON_0_ATI"; + case GL_CON_1_ATI: return "GL_CON_1_ATI"; + case GL_CON_2_ATI: return "GL_CON_2_ATI"; + case GL_CON_3_ATI: return "GL_CON_3_ATI"; + case GL_CON_4_ATI: return "GL_CON_4_ATI"; + case GL_CON_5_ATI: return "GL_CON_5_ATI"; + case GL_CON_6_ATI: return "GL_CON_6_ATI"; + case GL_CON_7_ATI: return "GL_CON_7_ATI"; + + case GL_ZERO: return "GL_ZERO"; + case GL_ONE: return "GL_ONE"; + case GL_PRIMARY_COLOR: return "GL_PRIMARY_COLOR"; + case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI"; + + default: return "Unknown register\n"; + } +} + +static const char *debug_swizzle(GLuint swizzle) { + switch(swizzle) { + case GL_SWIZZLE_STR_ATI: return "GL_SWIZZLE_STR_ATI"; + case GL_SWIZZLE_STQ_ATI: return "GL_SWIZZLE_STQ_ATI"; + case GL_SWIZZLE_STR_DR_ATI: return "GL_SWIZZLE_STR_DR_ATI"; + case GL_SWIZZLE_STQ_DQ_ATI: return "GL_SWIZZLE_STQ_DQ_ATI"; + default: return "unknown swizzle"; + } +} + +static const char *debug_rep(GLuint rep) { + switch(rep) { + case GL_NONE: return "GL_NONE"; + case GL_RED: return "GL_RED"; + case GL_GREEN: return "GL_GREEN"; + case GL_BLUE: return "GL_BLUE"; + default: return "unknown argrep"; + } +} + +#define GLINFO_LOCATION (*gl_info) +static GLuint register_for_arg(DWORD arg, WineD3D_GL_Info *gl_info, unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg) { + GLenum ret; + + if(mod) *mod = GL_NONE; + if(arg == ARG_UNUSED) return -1; /* This is the marker for unused registers */ + + switch(arg & WINED3DTA_SELECTMASK) { + case WINED3DTA_DIFFUSE: + ret = GL_PRIMARY_COLOR; + break; + + case WINED3DTA_CURRENT: + /* Note that using GL_REG_0_ATI for the passed on register is safe because + * texture0 is read at stage0, so in the worst case it is read in the + * instruction writing to reg0. Afterwards texture0 is not used any longer. + * If we're reading from current + */ + if(stage == 0) { + ret = GL_PRIMARY_COLOR; + } else { + ret = GL_REG_0_ATI; + } + break; + + case WINED3DTA_TEXTURE: + ret = GL_REG_0_ATI + stage; + break; + + case WINED3DTA_TFACTOR: + ret = ATI_FFP_CONST_TFACTOR; + break; + + case WINED3DTA_SPECULAR: + ret = GL_SECONDARY_INTERPOLATOR_ATI; + break; + + case WINED3DTA_TEMP: + ret = tmparg; + break; + + case WINED3DTA_CONSTANT: + FIXME("Unhandled source argument WINED3DTA_TEMP\n"); + ret = GL_CON_0_ATI; + break; + + default: + FIXME("Unknown source argument %d\n", arg); + ret = GL_ZERO; + } + + if(arg & WINED3DTA_COMPLEMENT) { + if(mod) *mod |= GL_COMP_BIT_ATI; + } + if(arg & WINED3DTA_ALPHAREPLICATE) { + if(rep) *rep = GL_ALPHA; + } else { + if(rep) *rep = GL_NONE; + } + return ret; +} + +static GLuint find_tmpreg(struct texture_stage_op op[MAX_TEXTURES]) { + int lowest_read = -1; + int lowest_write = -1; + int i; + BOOL tex_used[MAX_TEXTURES]; + + memset(tex_used, 0, sizeof(tex_used)); + for(i = 0; i < MAX_TEXTURES; i++) { + if(op[i].cop == WINED3DTOP_DISABLE) { + break; + } + + if(lowest_read == -1 && + (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP || + op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) { + lowest_read = i; + } + + if(lowest_write == -1 && op[i].dst == tempreg) { + lowest_write = i; + } + + if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE || + op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) { + tex_used[i] = TRUE; + } + } + + /* Temp reg not read? We don't need it, return GL_NONE */ + if(lowest_read == -1) return GL_NONE; + + if(lowest_write >= lowest_read) { + FIXME("Temp register read before being written\n"); + } + + if(lowest_write == -1) { + /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */ + FIXME("Temp register read without being written\n"); + return GL_REG_1_ATI; + } else if(lowest_write >= 1) { + /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result. + * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already + * read it + */ + return GL_REG_1_ATI; + } else { + /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used + * for the regular result + */ + for(i = 1; i < 6; i++) { + if(!tex_used[i]) { + return GL_REG_0_ATI + i; + } + } + /* What to do here? Report it in ValidateDevice? */ + FIXME("Could not find a register for the temporary register\n"); + return 0; + } +} + +static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_GL_Info *gl_info) { + GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1)); + unsigned int stage; + GLuint arg0, arg1, arg2, extrarg; + GLuint dstmod, argmod0, argmod1, argmod2, argmodextra; + GLuint rep0, rep1, rep2; + GLuint swizzle; + GLuint tmparg = find_tmpreg(op); + GLuint dstreg; + + if(!ret) { + ERR("Failed to generate a GL_ATI_fragment_shader shader id\n"); + return 0; + } + GL_EXTCALL(glBindFragmentShaderATI(ret)); + checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))"); + + TRACE("glBeginFragmentShaderATI()\n"); + GL_EXTCALL(glBeginFragmentShaderATI()); + checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())"); + + /* Pass 1: Generate sampling instructions for perturbation maps */ + for(stage = 0; stage < GL_LIMITS(textures); stage++) { + if(op[stage].cop == WINED3DTOP_DISABLE) break; + if(op[stage].cop != WINED3DTOP_BUMPENVMAP && + op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue; + + TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n", + stage, stage); + GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, + GL_TEXTURE0_ARB + stage, + GL_SWIZZLE_STR_ATI)); + if(op[stage + 1].projected == proj_none) { + swizzle = GL_SWIZZLE_STR_ATI; + } else if(op[stage + 1].projected == proj_count4) { + swizzle = GL_SWIZZLE_STQ_DQ_ATI; + } else { + swizzle = GL_SWIZZLE_STR_DR_ATI; + } + TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n", + stage + 1, stage + 1, debug_swizzle(swizzle)); + GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1, + GL_TEXTURE0_ARB + stage + 1, + swizzle)); + + /* We need GL_REG_5_ATI as a temporary register to swizzle the bump matrix. So we run into + * issues if we're bump mapping on stage 4 or 5 + */ + if(stage >= 4) { + FIXME("Bump mapping in stage %d\n", stage); + } + } + + /* Pass 2: Generate perturbation calculations */ + for(stage = 0; stage < GL_LIMITS(textures); stage++) { + if(op[stage].cop == WINED3DTOP_DISABLE) break; + if(op[stage].cop != WINED3DTOP_BUMPENVMAP && + op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue; + + /* Nice thing, we get the color correction for free :-) */ + if(op[stage].color_correction == WINED3DFMT_V8U8) { + argmodextra = GL_2X_BIT_ATI | GL_BIAS_BIT_ATI; + } else { + argmodextra = 0; + } + + TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_RED_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, ATI_FFP_CONST_BUMPMAT(%d), GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_RED, GL_NONE)\n", + stage + 1, stage, debug_argmod(argmodextra), stage, stage + 1); + GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE, + GL_REG_0_ATI + stage, GL_NONE, argmodextra, + ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI, + GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE)); + + /* FIXME: How can I make GL_DOT2_ADD_ATI read the factors from blue and alpha? It defaults to red and green, + * and it is fairly easy to make it read GL_BLUE or BL_ALPHA, but I can't get an R * B + G * A. So we're wasting + * one register and two instructions in this pass for a simple swizzling operation. + * For starters it might be good enough to merge the two movs into one, but even that isn't possible :-( + * + * NOTE: GL_BLUE | GL_ALPHA is not possible. It doesn't throw a compilation error, but an OR operation on the + * constants doesn't make sense, considering their values. + */ + TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_BLUE, GL_NONE)\n", stage); + GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, + ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE)); + TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_ALPHA, GL_NONE)\n", stage); + GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, + ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE)); + TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_GREEN_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, GL_REG_5_ATI, GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_GREEN, GL_NONE)\n", + stage + 1, stage, debug_argmod(argmodextra), stage + 1); + GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE, + GL_REG_0_ATI + stage, GL_NONE, argmodextra, + GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI, + GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE)); + } + + /* Pass 3: Generate sampling instructions for regular textures */ + for(stage = 0; stage < GL_LIMITS(textures); stage++) { + if(op[stage].cop == WINED3DTOP_DISABLE) { + break; + } + + if(op[stage].projected == proj_none) { + swizzle = GL_SWIZZLE_STR_ATI; + } else if(op[stage].projected == proj_count3) { + swizzle = GL_SWIZZLE_STR_DR_ATI; + } else { + swizzle = GL_SWIZZLE_STQ_DQ_ATI; + } + + if((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE || + op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) { + + if(stage > 0 && + (op[stage - 1].cop == WINED3DTOP_BUMPENVMAP || + op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) { + TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n", + stage, stage); + GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, + GL_REG_0_ATI + stage, + GL_SWIZZLE_STR_ATI)); + } else { + TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n", + stage, stage, debug_swizzle(swizzle)); + GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, + GL_TEXTURE0_ARB + stage, + swizzle)); + } + } + } + + /* Pass 4: Generate the arithmetic instructions */ + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(op[stage].cop == WINED3DTOP_DISABLE) { + if(stage == 0) { + /* Handle complete texture disabling gracefully */ + TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n"); + GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, + GL_PRIMARY_COLOR, GL_NONE, GL_NONE)); + TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n"); + GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, + GL_PRIMARY_COLOR, GL_NONE, GL_NONE)); + } + break; + } + + if(op[stage].dst == tempreg) { + /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place. + * skip the entire stage, this saves some GPU time + */ + if(tmparg == GL_NONE) continue; + + dstreg = tmparg; + } else { + dstreg = GL_REG_0_ATI; + } + + arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg); + arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg); + arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg); + dstmod = GL_NONE; + argmodextra = GL_NONE; + extrarg = GL_NONE; + + switch(op[stage].cop) { + case WINED3DTOP_SELECTARG2: + arg1 = arg2; + argmod1 = argmod2; + rep1 = rep2; + case WINED3DTOP_SELECTARG1: + TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s)\n", + debug_register(dstreg), debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1)); + GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE, GL_NONE, + arg1, rep1, argmod1)); + break; + + case WINED3DTOP_MODULATE4X: + if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI; + case WINED3DTOP_MODULATE2X: + if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI; + dstmod |= GL_SATURATE_BIT_ATI; + case WINED3DTOP_MODULATE: + TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2)); + GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, dstreg, GL_NONE, dstmod, + arg1, rep1, argmod1, + arg2, rep2, argmod2)); + break; + + case WINED3DTOP_ADDSIGNED2X: + dstmod = GL_2X_BIT_ATI; + case WINED3DTOP_ADDSIGNED: + argmodextra = GL_BIAS_BIT_ATI; + case WINED3DTOP_ADD: + dstmod |= GL_SATURATE_BIT_ATI; + TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmodextra | argmod2)); + GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod, + arg1, rep1, argmod1, + arg2, rep2, argmodextra | argmod2)); + break; + + case WINED3DTOP_SUBTRACT: + dstmod |= GL_SATURATE_BIT_ATI; + TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2)); + GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, dstreg, GL_NONE, dstmod, + arg1, rep1, argmod1, + arg2, rep2, argmod2)); + break; + + case WINED3DTOP_ADDSMOOTH: + argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; + TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1)); + /* Dst = arg1 + * arg2(1 -arg 1) + * = arg2 * (1 - arg1) + arg1 + */ + GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, + arg2, rep2, argmod2, + arg1, rep1, argmodextra, + arg1, rep1, argmod1)); + break; + + case WINED3DTOP_BLENDCURRENTALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDFACTORALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDTEXTUREALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDDIFFUSEALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1); + TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(extrarg), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE, + extrarg, GL_ALPHA, GL_NONE, + arg1, rep1, argmod1, + arg2, rep2, argmod2)); + break; + + case WINED3DTOP_BLENDTEXTUREALPHAPM: + arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); + TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg0), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_NONE, + arg2, rep2, argmod2, + arg0, GL_ALPHA, GL_COMP_BIT_ATI, + arg1, rep1, argmod1)); + break; + + /* D3DTOP_PREMODULATE ???? */ + + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + if(!argmodextra) argmodextra = argmod1; + TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, GL_ALPHA, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_rep(rep1), debug_argmod(arg1)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, + arg2, rep2, argmod2, + arg1, GL_ALPHA, argmodextra, + arg1, rep1, argmod1)); + break; + + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + if(!argmodextra) argmodextra = argmod1; + TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, GL_ALPHA, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra), + debug_register(arg1), debug_argmod(argmod1)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, + arg2, rep2, argmod2, + arg1, rep1, argmodextra, + arg1, GL_ALPHA, argmod1)); + break; + + case WINED3DTOP_DOTPRODUCT3: + TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, %s, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI)); + GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, + arg1, rep1, argmod1 | GL_BIAS_BIT_ATI, + arg2, rep2, argmod2 | GL_BIAS_BIT_ATI)); + break; + + case WINED3DTOP_MULTIPLYADD: + TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, + arg1, rep1, argmod1, + arg2, rep2, argmod2, + arg0, rep0, argmod0)); + break; + + case WINED3DTOP_LERP: + TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1), + debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2), + debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0)); + GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE, + arg0, rep0, argmod0, + arg1, rep1, argmod1, + arg2, rep2, argmod2)); + break; + + case WINED3DTOP_BUMPENVMAP: + case WINED3DTOP_BUMPENVMAPLUMINANCE: + /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */ + break; + + default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage); + } + + arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg); + arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg); + arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg); + dstmod = GL_NONE; + argmodextra = GL_NONE; + extrarg = GL_NONE; + + switch(op[stage].aop) { + case WINED3DTOP_DISABLE: + /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */ + if(stage == 0) { + TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n"); + GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, + GL_PRIMARY_COLOR, GL_NONE, GL_NONE)); + } + break; + + case WINED3DTOP_SELECTARG2: + arg1 = arg2; + argmod1 = argmod2; + case WINED3DTOP_SELECTARG1: + TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_argmod(argmod1)); + GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE, + arg1, GL_NONE, argmod1)); + break; + + case WINED3DTOP_MODULATE4X: + if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI; + case WINED3DTOP_MODULATE2X: + if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI; + dstmod |= GL_SATURATE_BIT_ATI; + case WINED3DTOP_MODULATE: + TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmod2)); + GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, dstreg, dstmod, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmod2)); + break; + + case WINED3DTOP_ADDSIGNED2X: + dstmod = GL_2X_BIT_ATI; + case WINED3DTOP_ADDSIGNED: + argmodextra = GL_BIAS_BIT_ATI; + case WINED3DTOP_ADD: + dstmod |= GL_SATURATE_BIT_ATI; + TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmodextra | argmod2)); + GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, dstreg, dstmod, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmodextra | argmod2)); + break; + + case WINED3DTOP_SUBTRACT: + dstmod |= GL_SATURATE_BIT_ATI; + TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), debug_dstmod(dstmod), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmod2)); + GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, dstreg, dstmod, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmod2)); + break; + + case WINED3DTOP_ADDSMOOTH: + argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; + TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_argmod(argmod2), + debug_register(arg1), debug_argmod(argmodextra), + debug_register(arg1), debug_argmod(argmod1)); + /* Dst = arg1 + * arg2(1 -arg 1) + * = arg2 * (1 - arg1) + arg1 + */ + GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI, + arg2, GL_NONE, argmod2, + arg1, GL_NONE, argmodextra, + arg1, GL_NONE, argmod1)); + break; + + case WINED3DTOP_BLENDCURRENTALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDFACTORALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDTEXTUREALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); + case WINED3DTOP_BLENDDIFFUSEALPHA: + if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1); + TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(extrarg), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmod2)); + GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, + extrarg, GL_ALPHA, GL_NONE, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmod2)); + break; + + case WINED3DTOP_BLENDTEXTUREALPHAPM: + arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); + TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg2), debug_argmod(argmod2), + debug_register(arg0), + debug_register(arg1), debug_argmod(argmod1)); + GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, + arg2, GL_NONE, argmod2, + arg0, GL_ALPHA, GL_COMP_BIT_ATI, + arg1, GL_NONE, argmod1)); + break; + + /* D3DTOP_PREMODULATE ???? */ + + case WINED3DTOP_DOTPRODUCT3: + TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, %s, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), + debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI)); + GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, + arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI, + arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI)); + break; + + case WINED3DTOP_MULTIPLYADD: + TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmod2), + debug_register(arg0), debug_argmod(argmod0)); + GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmod2, + arg0, GL_NONE, argmod0)); + break; + + case WINED3DTOP_LERP: + TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n", + debug_register(dstreg), + debug_register(arg1), debug_argmod(argmod1), + debug_register(arg2), debug_argmod(argmod2), + debug_register(arg0), debug_argmod(argmod0)); + GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_SATURATE_BIT_ATI, + arg1, GL_NONE, argmod1, + arg2, GL_NONE, argmod2, + arg0, GL_NONE, argmod0)); + break; + + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + case WINED3DTOP_BUMPENVMAP: + case WINED3DTOP_BUMPENVMAPLUMINANCE: + ERR("Application uses an invalid alpha operation\n"); + break; + + default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage); + } + } + + TRACE("glEndFragmentShaderATI()\n"); + GL_EXTCALL(glEndFragmentShaderATI()); + checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())"); + return ret; +} +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + IWineD3DDeviceImpl *This = stateblock->wineD3DDevice; + struct atifs_ffp_desc *desc; + struct ffp_settings settings; + struct atifs_private_data *priv = (struct atifs_private_data *) This->fragment_priv; + DWORD mapped_stage; + unsigned int i; + + gen_ffp_op(stateblock, &settings, TRUE); + desc = (struct atifs_ffp_desc *) find_ffp_shader(priv->fragment_shaders, &settings); + if(!desc) { + desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc)); + if(!desc) { + ERR("Out of memory\n"); + return; + } + desc->num_textures_used = 0; + for(i = 0; i < GL_LIMITS(texture_stages); i++) { + if(settings.op[i].cop == WINED3DTOP_DISABLE) break; + desc->num_textures_used = i; + } + + memcpy(&desc->parent.settings, &settings, sizeof(settings)); + desc->shader = gen_ati_shader(settings.op, &GLINFO_LOCATION); + add_ffp_shader(priv->fragment_shaders, &desc->parent); + TRACE("Allocated fixed function replacement shader descriptor %p\n", desc); + } + + /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages + * used by this shader + */ + for(i = 0; i < desc->num_textures_used; i++) { + mapped_stage = This->texUnitMap[i]; + if(mapped_stage != -1) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + texture_activate_dimensions(i, stateblock, context); + } + } + + GL_EXTCALL(glBindFragmentShaderATI(desc->shader)); +} + +static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float col[4]; + D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); + + GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)); + checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)"); +} + +static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + float mat[2][2]; + + mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); + mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]); + mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]); + mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]); + /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat + * constants can be in any range. While they should stay between [-1.0 and 1.0] because + * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally, + * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the + * shader(it is free). This might potentially reduce precision. However, if the hardware does + * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway + */ + mat[0][0] = (mat[0][0] + 1.0) * 0.5; + mat[1][0] = (mat[1][0] + 1.0) * 0.5; + mat[0][1] = (mat[0][1] + 1.0) * 0.5; + mat[1][1] = (mat[1][1] + 1.0) * 0.5; + GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), (float *) mat)); + checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), mat)"); +} + +static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(!isStateDirty(context, STATE_PIXELSHADER)) { + set_tex_op_atifs(state, stateblock, context); + } +} + +#undef GLINFO_LOCATION + +static const struct StateEntryTemplate atifs_fragmentstate_template[] = { + {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 }, + {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; + +static void atifs_enable(IWineD3DDevice *iface, BOOL enable) { + if(enable) { + glEnable(GL_FRAGMENT_SHADER_ATI); + checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)"); + } else { + glDisable(GL_FRAGMENT_SHADER_ATI); + checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)"); + } +} + +static void atifs_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *caps) { + caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | + WINED3DTEXOPCAPS_SELECTARG1 | + WINED3DTEXOPCAPS_SELECTARG2 | + WINED3DTEXOPCAPS_MODULATE4X | + WINED3DTEXOPCAPS_MODULATE2X | + WINED3DTEXOPCAPS_MODULATE | + WINED3DTEXOPCAPS_ADDSIGNED2X | + WINED3DTEXOPCAPS_ADDSIGNED | + WINED3DTEXOPCAPS_ADD | + WINED3DTEXOPCAPS_SUBTRACT | + WINED3DTEXOPCAPS_ADDSMOOTH | + WINED3DTEXOPCAPS_BLENDCURRENTALPHA | + WINED3DTEXOPCAPS_BLENDFACTORALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | + WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM | + WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_DOTPRODUCT3 | + WINED3DTEXOPCAPS_MULTIPLYADD | + WINED3DTEXOPCAPS_LERP | + WINED3DTEXOPCAPS_BUMPENVMAP; + + /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE + and WINED3DTEXOPCAPS_PREMODULATE */ + + /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards + * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program). + * If the current card has more than 8 fixed function textures in OpenGL's regular fixed + * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This + * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp + * pipeline, and almost all games are happy with that. We can however support up to 8 + * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use + * only 1 instruction. + * + * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the + * r200 series and use an ARB or GLSL shader instead + */ + caps->MaxTextureBlendStages = 8; + caps->MaxSimultaneousTextures = 6; + + caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; +} + +static HRESULT atifs_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct atifs_private_data *priv; + + This->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct atifs_private_data)); + if(!This->fragment_priv) { + ERR("Out of memory\n"); + return E_OUTOFMEMORY; + } + priv = (struct atifs_private_data *) This->fragment_priv; + priv->fragment_shaders = hash_table_create(ffp_program_key_hash, ffp_program_key_compare); + return WINED3D_OK; +} + +#define GLINFO_LOCATION This->adapter->gl_info +static void atifs_free_ffpshader(void *value, void *device) { + IWineD3DDeviceImpl *This = device; + struct atifs_ffp_desc *entry_ati = value; + + ENTER_GL(); + GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader)); + checkGLcall("glDeleteFragmentShaderATI(entry->shader)"); + HeapFree(GetProcessHeap(), 0, entry_ati); + LEAVE_GL(); +} + +static void atifs_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct atifs_private_data *priv = (struct atifs_private_data *) This->fragment_priv; + + hash_table_destroy(priv->fragment_shaders, atifs_free_ffpshader, This); + + HeapFree(GetProcessHeap(), 0, priv); + This->fragment_priv = NULL; +} +#undef GLINFO_LOCATION + +static BOOL atifs_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt)); + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + TRACE("[OK]\n"); + return TRUE; + default: + TRACE("[FAILED\n"); + return FALSE; + } +} + +const struct fragment_pipeline atifs_fragment_pipeline = { + atifs_enable, + atifs_get_caps, + atifs_alloc, + atifs_free, + atifs_conv_supported, + atifs_fragmentstate_template, + TRUE /* We can disable projected textures */ +}; diff --git a/reactos/dll/directx/wine/wined3d/baseshader.c b/reactos/dll/directx/wine/wined3d/baseshader.c index 638db902f08..82187fc1a11 100644 --- a/reactos/dll/directx/wine/wined3d/baseshader.c +++ b/reactos/dll/directx/wine/wined3d/baseshader.c @@ -6,6 +6,7 @@ * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber * Copyright 2006 Ivan Gyurdiev + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -125,7 +126,7 @@ static inline int shader_skip_opcode( DWORD opcode_token) { /* Shaders >= 2.0 may contain address tokens, but fortunately they - * have a useful legnth mask - use it here. Shaders 1.0 contain no such tokens */ + * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */ return (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT): @@ -153,8 +154,8 @@ int shader_skip_unrecognized( tokens_read += shader_get_param(iface, pToken, ¶m, &addr_token); pToken += tokens_read; - FIXME("Unrecognized opcode param: token=%08x " - "addr_token=%08x name=", param, addr_token); + FIXME("Unrecognized opcode param: token=0x%08x " + "addr_token=0x%08x name=", param, addr_token); shader_dump_param(iface, param, addr_token, i); FIXME("\n"); ++i; @@ -181,6 +182,20 @@ unsigned int shader_get_float_offset(const DWORD reg) { } } +static void shader_delete_constant_list(struct list* clist) { + + struct list *ptr; + struct local_constant* constant; + + ptr = list_head(clist); + while (ptr) { + constant = LIST_ENTRY(ptr, struct local_constant, entry); + ptr = list_next(clist, ptr); + HeapFree(GetProcessHeap(), 0, constant); + } + list_init(clist); +} + /* Note that this does not count the loop register * as an address register. */ @@ -198,12 +213,19 @@ HRESULT shader_get_registers_used( /* There are some minor differences between pixel and vertex shaders */ char pshader = shader_is_pshader_version(This->baseShader.hex_version); - reg_maps->bumpmat = -1; - reg_maps->luminanceparams = -1; + memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat)); + memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams)); if (pToken == NULL) return WINED3D_OK; + /* get_registers_used is called on every compile on some 1.x shaders, which can result + * in stacking up a collection of local constants. Delete the old constants if existing + */ + shader_delete_constant_list(&This->baseShader.constantsF); + shader_delete_constant_list(&This->baseShader.constantsB); + shader_delete_constant_list(&This->baseShader.constantsI); + while (WINED3DVS_END() != *pToken) { CONST SHADER_OPCODE* curOpcode; DWORD opcode_token; @@ -267,7 +289,7 @@ HRESULT shader_get_registers_used( local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); if (!lconst) return E_OUTOFMEMORY; lconst->idx = *pToken & WINED3DSP_REGNUM_MASK; - memcpy(&lconst->value, pToken + 1, 4 * sizeof(DWORD)); + memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD)); /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */ if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && pshader) { @@ -290,7 +312,7 @@ HRESULT shader_get_registers_used( local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); if (!lconst) return E_OUTOFMEMORY; lconst->idx = *pToken & WINED3DSP_REGNUM_MASK; - memcpy(&lconst->value, pToken + 1, 4 * sizeof(DWORD)); + memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD)); list_add_head(&This->baseShader.constantsI, &lconst->entry); pToken += curOpcode->num_params; @@ -299,7 +321,7 @@ HRESULT shader_get_registers_used( local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); if (!lconst) return E_OUTOFMEMORY; lconst->idx = *pToken & WINED3DSP_REGNUM_MASK; - memcpy(&lconst->value, pToken + 1, 1 * sizeof(DWORD)); + memcpy(lconst->value, pToken + 1, 1 * sizeof(DWORD)); list_add_head(&This->baseShader.constantsB, &lconst->entry); pToken += curOpcode->num_params; @@ -327,7 +349,8 @@ HRESULT shader_get_registers_used( int i, limit; /* Declare 1.X samplers implicitly, based on the destination reg. number */ - if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && + if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && + pshader /* Filter different instructions with the same enum values in VS */ && (WINED3DSIO_TEX == curOpcode->opcode || WINED3DSIO_TEXBEM == curOpcode->opcode || WINED3DSIO_TEXBEML == curOpcode->opcode || @@ -349,6 +372,10 @@ HRESULT shader_get_registers_used( } else { int texType = IWineD3DBaseTexture_GetTextureDimensions(stateBlock->textures[sampler_code]); switch(texType) { + /* We have to select between texture rectangles and 2D textures later because 2.0 and + * 3.0 shaders only have WINED3DSTT_2D as well + */ + case GL_TEXTURE_RECTANGLE_ARB: case GL_TEXTURE_2D: reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D; break; @@ -370,25 +397,17 @@ HRESULT shader_get_registers_used( /* texbem is only valid with < 1.4 pixel shaders */ if(WINED3DSIO_TEXBEM == curOpcode->opcode || WINED3DSIO_TEXBEML == curOpcode->opcode) { - if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) { - FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n"); - } else { - reg_maps->bumpmat = sampler_code; - if(WINED3DSIO_TEXBEML == curOpcode->opcode) { - reg_maps->luminanceparams = sampler_code; - } + reg_maps->bumpmat[sampler_code] = TRUE; + if(WINED3DSIO_TEXBEML == curOpcode->opcode) { + reg_maps->luminanceparams[sampler_code] = TRUE; } } } if(WINED3DSIO_NRM == curOpcode->opcode) { reg_maps->usesnrm = 1; - } else if(WINED3DSIO_BEM == curOpcode->opcode) { + } else if(WINED3DSIO_BEM == curOpcode->opcode && pshader) { DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK; - if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != regnum) { - FIXME("Pixel shader uses bem or texbem instruction on more than 1 sampler\n"); - } else { - reg_maps->bumpmat = regnum; - } + reg_maps->bumpmat[regnum] = TRUE; } else if(WINED3DSIO_DSY == curOpcode->opcode) { reg_maps->usesdsy = 1; } @@ -459,6 +478,15 @@ HRESULT shader_get_registers_used( reg_maps->usesrelconstF = TRUE; } } + + /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used + * in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT + * isn't used in them, but future register types might cause issues + */ + else if(WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */ && + !pshader && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) < 3) { + reg_maps->texcoord_mask[reg] |= shader_get_writemask(param); + } } } } @@ -483,7 +511,7 @@ static void shader_dump_decl_usage( case WINED3DSTT_2D: TRACE("_2d"); break; case WINED3DSTT_CUBE: TRACE("_cube"); break; case WINED3DSTT_VOLUME: TRACE("_volume"); break; - default: TRACE("_unknown_ttype(%08x)", ttype); + default: TRACE("_unknown_ttype(0x%08x)", ttype); } } else { @@ -546,7 +574,7 @@ static void shader_dump_decl_usage( TRACE("sample"); break; default: - FIXME("unknown_semantics(%08x)", usage); + FIXME("unknown_semantics(0x%08x)", usage); } } } @@ -753,8 +781,7 @@ void shader_dump_param( /** Shared code in order to generate the bulk of the shader string. Use the shader_header_fct & shader_footer_fct to add strings that are specific to pixel or vertex functions - NOTE: A description of how to parse tokens can be found at: - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/graphics/hh/graphics/usermodedisplaydriver_shader_cc8e4e05-f5c3-4ec0-8853-8ce07c1551b2.xml.asp */ + NOTE: A description of how to parse tokens can be found on msdn */ void shader_generate_main( IWineD3DBaseShader *iface, SHADER_BUFFER* buffer, @@ -808,7 +835,7 @@ void shader_generate_main( /* Unknown opcode and its parameters */ if (NULL == curOpcode) { - FIXME("Unrecognized opcode: token=%08x\n", hw_arg.opcode_token); + FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token); pToken += shader_skip_unrecognized(iface, pToken); /* Nothing to do */ @@ -936,7 +963,7 @@ void shader_trace_init( if (NULL == curOpcode) { int tokens_read; - FIXME("Unrecognized opcode: token=%08x\n", opcode_token); + FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token); tokens_read = shader_skip_unrecognized(iface, pToken); pToken += tokens_read; len += tokens_read; @@ -1062,34 +1089,63 @@ void shader_trace_init( } } -static void shader_delete_constant_list( - struct list* clist) { - - struct list *ptr; - struct local_constant* constant; - - ptr = list_head(clist); - while (ptr) { - constant = LIST_ENTRY(ptr, struct local_constant, entry); - ptr = list_next(clist, ptr); - HeapFree(GetProcessHeap(), 0, constant); - } -} - static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {} static void shader_none_select_depth_blt(IWineD3DDevice *iface) {} +static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {} static void shader_none_cleanup(IWineD3DDevice *iface) {} static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {} static void shader_none_destroy(IWineD3DBaseShader *iface) {} +static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;} +static void shader_none_free(IWineD3DDevice *iface) {} +static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;} +static void shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) { + FIXME("NONE shader backend asked to generate a pixel shader\n"); +} +static void shader_none_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) { + FIXME("NONE shader backend asked to generate a vertex shader\n"); +} + +#define GLINFO_LOCATION (*gl_info) +static void shader_none_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) { + /* Set the shader caps to 0 for the none shader backend */ + pCaps->VertexShaderVersion = 0; + pCaps->PixelShaderVersion = 0; + pCaps->PixelShader1xMaxValue = 0.0; +} +#undef GLINFO_LOCATION +static BOOL shader_none_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s", debug_d3dformat(fmt)); + switch(fmt) { + /* Faked to make some apps happy. */ + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_Q8W8V8U8: + TRACE("[OK]\n"); + return TRUE; + default: + TRACE("[FAILED]\n"); + return FALSE; + } +} const shader_backend_t none_shader_backend = { - &shader_none_select, - &shader_none_select_depth_blt, - &shader_none_load_constants, - &shader_none_cleanup, - &shader_none_color_correction, - &shader_none_destroy + shader_none_select, + shader_none_select_depth_blt, + shader_none_deselect_depth_blt, + shader_none_load_constants, + shader_none_cleanup, + shader_none_color_correction, + shader_none_destroy, + shader_none_alloc, + shader_none_free, + shader_none_dirty_const, + shader_none_generate_pshader, + shader_none_generate_vshader, + shader_none_get_caps, + shader_none_conv_supported }; /* ******************************************* @@ -1129,6 +1185,7 @@ ULONG WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface) { shader_delete_constant_list(&This->baseShader.constantsF); shader_delete_constant_list(&This->baseShader.constantsB); shader_delete_constant_list(&This->baseShader.constantsI); + list_remove(&This->baseShader.shader_list_entry); HeapFree(GetProcessHeap(), 0, This); } return ref; diff --git a/reactos/dll/directx/wine/wined3d/basetexture.c b/reactos/dll/directx/wine/wined3d/basetexture.c index a1290f869ce..ffc01e8fa7a 100644 --- a/reactos/dll/directx/wine/wined3d/basetexture.c +++ b/reactos/dll/directx/wine/wined3d/basetexture.c @@ -4,6 +4,7 @@ * Copyright 2002-2004 Jason Edmeades * Copyright 2002-2004 Raphael Junqueira * Copyright 2005 Oliver Stieber + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -111,6 +112,20 @@ void WINAPI IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *ifac IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface); } +void WINAPI IWineD3DBaseTextureImpl_UnLoad(IWineD3DBaseTexture *iface) { + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + if(This->baseTexture.textureName) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + glDeleteTextures(1, &This->baseTexture.textureName); + This->baseTexture.textureName = 0; + LEAVE_GL(); + } + This->baseTexture.dirty = TRUE; +} + WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -123,7 +138,7 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUn IWineD3DBaseTexture IWineD3DBaseTexture parts follow ****************************************************** */ -/* There is no OpenGL equivilent of setLOD, getLOD, all they do it priortise testure loading +/* There is no OpenGL equivalent of setLOD, getLOD. All they do anyway is prioritize texture loading * so just pretend that they work unless something really needs a failure. */ DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; @@ -183,10 +198,12 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST)"); + break; case WINED3DTEXF_LINEAR: glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)"); + break; default: WARN("Unexpected filter type %d, setting to GL_NICEST\n", FilterType); glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); @@ -285,13 +302,19 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) { checkGLcall("glBindTexture"); if (isNewTexture) { /* For a new texture we have to set the textures levels after binding the texture. - * In theory this is all we should ever have to do, but because ATI's drivers are broken, we - * also need to set the texture dimensions before the texture is set */ - 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)"); + * In theory this is all we should ever have to do, but because ATI's drivers are broken, we + * also need to set the texture dimensions before the texture is set + * Beware that texture rectangles do not support mipmapping, but set the maxmiplevel if we're + * 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_CUBE_MAP_ARB) { - /* Cubemaps are always set to clamp, regardeless of the sampler state. */ + /* Cubemaps are always set to clamp, regardless of the sampler state. */ glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); @@ -307,32 +330,18 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) { return hr; } -HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) { - IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - UINT textureDimensions; - - TRACE("(%p) : About to bind texture\n", This); - textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); - - ENTER_GL(); - - glBindTexture(textureDimensions, 0); -#if 0 /* TODO: context manager support */ - IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */); -#else - glDisable(textureDimensions); -#endif - - LEAVE_GL(); - return WINED3D_OK; -} - UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){ IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; FIXME("(%p) : This shouldn't be called\n", This); return WINED3D_OK; } +BOOL WINAPI IWineD3DBaseTextureImpl_IsCondNP2(IWineD3DBaseTexture *iface){ + IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; + FIXME("(%p) : This shouldn't be called\n", This); + return FALSE; +} + static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) { switch(Type) { case WINED3DSAMP_ADDRESSU: @@ -347,15 +356,22 @@ static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) { } } -static inline void apply_wrap(const GLint textureDimensions, const DWORD state, const GLint type) { +static inline void apply_wrap(const GLint textureDimensions, const DWORD state, const GLint type, + BOOL cond_np2) { GLint wrapParm; if (state < minLookup[WINELOOKUP_WARPPARAM] || state > maxLookup[WINELOOKUP_WARPPARAM]) { FIXME("Unrecognized or unsupported WINED3DTADDRESS_U value %d\n", state); } else { if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) { - /* Cubemaps are always set to clamp, regardeless of the sampler state. */ + /* Cubemaps are always set to clamp, regardless of the sampler state. */ wrapParm = GL_CLAMP_TO_EDGE; + } else if(cond_np2) { + if(state == WINED3DTADDRESS_WRAP) { + wrapParm = GL_CLAMP_TO_EDGE; + } else { + wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]]; + } } else { wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]]; } @@ -371,24 +387,25 @@ void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; DWORD state; GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); + BOOL cond_np2 = IWineD3DBaseTexture_IsCondNP2(iface); - IWineD3DBaseTexture_PreLoad(iface); + /* ApplyStateChanges relies on the correct texture being bound and loaded. */ if(samplerStates[WINED3DSAMP_ADDRESSU] != This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]) { state = samplerStates[WINED3DSAMP_ADDRESSU]; - apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_S); + apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_S, cond_np2); This->baseTexture.states[WINED3DTEXSTA_ADDRESSU] = state; } if(samplerStates[WINED3DSAMP_ADDRESSV] != This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]) { state = samplerStates[WINED3DSAMP_ADDRESSV]; - apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_T); + apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_T, cond_np2); This->baseTexture.states[WINED3DTEXSTA_ADDRESSV] = state; } if(samplerStates[WINED3DSAMP_ADDRESSW] != This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]) { state = samplerStates[WINED3DSAMP_ADDRESSW]; - apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_R); + apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_R, cond_np2); This->baseTexture.states[WINED3DTEXSTA_ADDRESSW] = state; } @@ -406,31 +423,31 @@ void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface if(samplerStates[WINED3DSAMP_MAGFILTER] != This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]) { GLint glValue; state = samplerStates[WINED3DSAMP_MAGFILTER]; - if (state < minLookup[WINELOOKUP_MAGFILTER] || state > maxLookup[WINELOOKUP_MAGFILTER]) { + if (state > WINED3DTEXF_ANISOTROPIC) { FIXME("Unrecognized or unsupported MAGFILTER* value %d\n", state); + } else { + glValue = (*This->baseTexture.magLookup)[state - WINED3DTEXF_NONE]; + TRACE("ValueMAG=%d setting MAGFILTER to %x\n", state, glValue); + glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue); + /* We need to reset the Anisotropic filtering state when we change the mag filter to WINED3DTEXF_ANISOTROPIC (this seems a bit weird, check the documentation to see how it should be switched off. */ + if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == state && + !cond_np2) { + glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]); + } + This->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = state; } - glValue = stateLookup[WINELOOKUP_MAGFILTER][state - minLookup[WINELOOKUP_MAGFILTER]]; - TRACE("ValueMAG=%d setting MAGFILTER to %x\n", state, glValue); - glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue); - /* We need to reset the Aniotropic filtering state when we change the mag filter to WINED3DTEXF_ANISOTROPIC (this seems a bit weird, check the documentataion to see how it should be switched off. */ - if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == state) { - glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]); - } - This->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = state; } - if(samplerStates[WINED3DSAMP_MINFILTER] != This->baseTexture.states[WINED3DTEXSTA_MINFILTER] || - samplerStates[WINED3DSAMP_MIPFILTER] != This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] || - samplerStates[WINED3DSAMP_MAXMIPLEVEL] != This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]) { + if((samplerStates[WINED3DSAMP_MINFILTER] != This->baseTexture.states[WINED3DTEXSTA_MINFILTER] || + samplerStates[WINED3DSAMP_MIPFILTER] != This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] || + samplerStates[WINED3DSAMP_MAXMIPLEVEL] != This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL])) { GLint glValue; This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER]; This->baseTexture.states[WINED3DTEXSTA_MINFILTER] = samplerStates[WINED3DSAMP_MINFILTER]; This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] = samplerStates[WINED3DSAMP_MAXMIPLEVEL]; - if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < WINED3DTEXF_NONE || - This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < WINED3DTEXF_NONE || - This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC || + if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC || This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR) { @@ -438,7 +455,8 @@ void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface This->baseTexture.states[WINED3DTEXSTA_MINFILTER], This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]); } - glValue = minMipLookup[min(max(samplerStates[WINED3DSAMP_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)] + glValue = (*This->baseTexture.minMipLookup) + [min(max(samplerStates[WINED3DSAMP_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)] [min(max(samplerStates[WINED3DSAMP_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)]; TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", @@ -447,18 +465,20 @@ void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue); checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ..."); - if(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) { - glValue = 0; - } else if(This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) { - glValue = This->baseTexture.levels - 1; - } else { - glValue = This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]; + if(!cond_np2) { + if(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) { + glValue = 0; + } else if(This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) { + glValue = This->baseTexture.levels - 1; + } else { + glValue = This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]; + } + glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue); } - glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue); } if(samplerStates[WINED3DSAMP_MAXANISOTROPY] != This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY]) { - if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) { + if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && !cond_np2) { glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]); checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ..."); } else { @@ -484,6 +504,7 @@ static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl = IWineD3DBaseTextureImpl_SetPriority, IWineD3DBaseTextureImpl_GetPriority, IWineD3DBaseTextureImpl_PreLoad, + IWineD3DBaseTextureImpl_UnLoad, IWineD3DBaseTextureImpl_GetType, /*IWineD3DBaseTexture*/ IWineD3DBaseTextureImpl_SetLOD, @@ -496,8 +517,8 @@ static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl = IWineD3DBaseTextureImpl_GetDirty, /* internal */ IWineD3DBaseTextureImpl_BindTexture, - IWineD3DBaseTextureImpl_UnBindTexture, IWineD3DBaseTextureImpl_GetTextureDimensions, + IWineD3DBaseTextureImpl_IsCondNP2, IWineD3DBaseTextureImpl_ApplyStateChanges }; diff --git a/reactos/dll/directx/wine/wined3d/context.c b/reactos/dll/directx/wine/wined3d/context.c index 32d75b60835..76d449ad7ea 100644 --- a/reactos/dll/directx/wine/wined3d/context.c +++ b/reactos/dll/directx/wine/wined3d/context.c @@ -1,7 +1,7 @@ /* * Context and render target management in wined3d * - * Copyright 2007 Stefan Dösinger for CodeWeavers + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,296 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); #define GLINFO_LOCATION This->adapter->gl_info +/* The last used device. + * + * If the application creates multiple devices and switches between them, ActivateContext has to + * change the opengl context. This flag allows to keep track which device is active + */ +static IWineD3DDeviceImpl *last_device; + +/* FBO helper functions */ + +void context_bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) +{ + const IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + + if (!*fbo) + { + GL_EXTCALL(glGenFramebuffersEXT(1, fbo)); + checkGLcall("glGenFramebuffersEXT()"); + TRACE("Created FBO %d\n", *fbo); + } + + GL_EXTCALL(glBindFramebufferEXT(target, *fbo)); + checkGLcall("glBindFramebuffer()"); +} + +static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) +{ + int i = 0; + + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fbo)); + checkGLcall("glBindFramebuffer()"); + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2D()"); + } + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2D()"); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glBindFramebuffer()"); + GL_EXTCALL(glDeleteFramebuffersEXT(1, fbo)); + checkGLcall("glDeleteFramebuffers()"); +} + +static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD3DSurface *surface, BOOL force_preload) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; + IWineD3DBaseTextureImpl *texture_impl; + BOOL update_minfilter, update_magfilter; + + /* Update base texture states array */ + if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) + { + if (texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] != WINED3DTEXF_POINT) + { + texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; + update_minfilter = TRUE; + } + + if (texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] != WINED3DTEXF_POINT) + { + texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; + update_magfilter = TRUE; + } + + if (texture_impl->baseTexture.bindCount) + { + WARN("Render targets should not be bound to a sampler\n"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler)); + } + + IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl); + } + + if (update_minfilter || update_magfilter || force_preload) + { + GLenum target, bind_target; + GLint old_binding; + + target = surface_impl->glDescription.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); + } + + IWineD3DSurface_PreLoad(surface); + + glBindTexture(bind_target, surface_impl->glDescription.textureName); + 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()"); +} + +/* TODO: Handle stencil attachments */ +void context_attach_depth_stencil_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) +{ + IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil; + + TRACE("Attach depth stencil %p\n", depth_stencil); + + if (depth_stencil) + { + if (use_render_buffer && depth_stencil_impl->current_renderbuffer) + { + GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id)); + checkGLcall("glFramebufferRenderbufferEXT()"); + } else { + context_apply_attachment_filter_states((IWineD3DDevice *)This, depth_stencil, TRUE); + + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, depth_stencil_impl->glDescription.target, + depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level)); + checkGLcall("glFramebufferTexture2DEXT()"); + } + } else { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2DEXT()"); + } +} + +void context_attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) +{ + const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; + + TRACE("Attach surface %p to %u\n", surface, idx); + + if (surface) + { + context_apply_attachment_filter_states((IWineD3DDevice *)This, surface, TRUE); + + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, surface_impl->glDescription.target, + surface_impl->glDescription.textureName, surface_impl->glDescription.level)); + checkGLcall("glFramebufferTexture2DEXT()"); + } else { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2DEXT()"); + } +} + +static void context_check_fbo_status(IWineD3DDevice *iface) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + GLenum status; + + status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); + if (status == GL_FRAMEBUFFER_COMPLETE_EXT) + { + TRACE("FBO complete\n"); + } else { + IWineD3DSurfaceImpl *attachment; + int i; + FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status); + + /* Dump the FBO attachments */ + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + attachment = (IWineD3DSurfaceImpl *)This->activeContext->current_fbo->render_targets[i]; + if (attachment) + { + FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format), + attachment->pow2Width, attachment->pow2Height); + } + } + attachment = (IWineD3DSurfaceImpl *)This->activeContext->current_fbo->depth_stencil; + if (attachment) + { + FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format), + attachment->pow2Width, attachment->pow2Height); + } + } +} + +static struct fbo_entry *context_create_fbo_entry(IWineD3DDevice *iface) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct fbo_entry *entry; + + entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); + entry->render_targets = HeapAlloc(GetProcessHeap(), 0, GL_LIMITS(buffers) * sizeof(*entry->render_targets)); + memcpy(entry->render_targets, This->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)); + entry->depth_stencil = This->stencilBufferTarget; + entry->attached = FALSE; + entry->id = 0; + + return entry; +} + +void context_destroy_fbo_entry(IWineD3DDeviceImpl *This, struct fbo_entry *entry) +{ + if (entry->id) + { + TRACE("Destroy FBO %d\n", entry->id); + context_destroy_fbo(This, &entry->id); + } + list_remove(&entry->entry); + HeapFree(GetProcessHeap(), 0, entry->render_targets); + HeapFree(GetProcessHeap(), 0, entry); +} + + +static struct fbo_entry *context_find_fbo_entry(IWineD3DDevice *iface, WineD3DContext *context) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct fbo_entry *entry; + + LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) + { + if (!memcmp(entry->render_targets, This->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)) + && entry->depth_stencil == This->stencilBufferTarget) + { + return entry; + } + } + + entry = context_create_fbo_entry(iface); + list_add_head(&context->fbo_list, &entry->entry); + return entry; +} + +static void context_apply_fbo_entry(IWineD3DDevice *iface, struct fbo_entry *entry) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + unsigned int i; + + context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &entry->id); + + if (!entry->attached) + { + /* Apply render targets */ + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + IWineD3DSurface *render_target = This->render_targets[i]; + context_attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, i, render_target); + } + + /* Apply depth targets */ + if (This->stencilBufferTarget) { + unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width; + unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height; + + surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h); + } + context_attach_depth_stencil_fbo(This, GL_FRAMEBUFFER_EXT, This->stencilBufferTarget, TRUE); + + entry->attached = TRUE; + } else { + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + if (This->render_targets[i]) + context_apply_attachment_filter_states(iface, This->render_targets[i], FALSE); + } + if (This->stencilBufferTarget) + context_apply_attachment_filter_states(iface, This->stencilBufferTarget, FALSE); + } + + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + if (This->render_targets[i]) + This->draw_buffers[i] = GL_COLOR_ATTACHMENT0_EXT + i; + else + This->draw_buffers[i] = GL_NONE; + } +} + +static void context_apply_fbo_state(IWineD3DDevice *iface) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3DContext *context = This->activeContext; + + if (This->render_offscreen) + { + context->current_fbo = context_find_fbo_entry(iface, context); + context_apply_fbo_entry(iface, context->current_fbo); + } else { + context->current_fbo = NULL; + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + } + + context_check_fbo_status(iface); +} + /***************************************************************************** * Context_MarkStateDirty * @@ -39,9 +329,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); * Params: * context: Context to mark the state dirty in * state: State to mark dirty + * StateTable: Pointer to the state table in use(for state grouping) * *****************************************************************************/ -static void Context_MarkStateDirty(WineD3DContext *context, DWORD state) { +static void Context_MarkStateDirty(WineD3DContext *context, DWORD state, const struct StateEntry *StateTable) { DWORD rep = StateTable[state].representative; DWORD idx; BYTE shift; @@ -101,7 +392,7 @@ static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_hand /* 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++) { - Context_MarkStateDirty(This->contexts[This->numContexts], state); + Context_MarkStateDirty(This->contexts[This->numContexts], state, This->StateTable); } This->numContexts++; @@ -109,6 +400,179 @@ static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_hand return This->contexts[This->numContexts - 1]; } +/* This function takes care of WineD3D pixel format selection. */ +static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, WINED3DFORMAT ColorFormat, WINED3DFORMAT DepthStencilFormat, BOOL auxBuffers, int numSamples, BOOL pbuffer, BOOL findCompatible) +{ + int iPixelFormat=0, matchtry; + short redBits, greenBits, blueBits, alphaBits, colorBits; + short depthBits=0, stencilBits=0; + + struct match_type { + BOOL require_aux; + BOOL exact_alpha; + BOOL exact_color; + } matches[] = { + /* First, try without alpha match buffers. MacOS supports aux buffers only + * on A8R8G8B8, and we prefer better offscreen rendering over an alpha match. + * Then try without aux buffers - this is the most common cause for not + * finding a pixel format. Also some drivers(the open source ones) + * only offer 32 bit ARB pixel formats. First try without an exact alpha + * match, then try without an exact alpha and color match. + */ + { TRUE, TRUE, TRUE }, + { TRUE, FALSE, TRUE }, + { FALSE, TRUE, TRUE }, + { FALSE, FALSE, TRUE }, + { TRUE, FALSE, FALSE }, + { FALSE, FALSE, FALSE }, + }; + + int i = 0; + int nCfgs = This->adapter->nCfgs; + WineD3D_PixelFormat *cfgs = This->adapter->cfgs; + + TRACE("ColorFormat=%s, DepthStencilFormat=%s, auxBuffers=%d, numSamples=%d, pbuffer=%d, findCompatible=%d\n", + debug_d3dformat(ColorFormat), debug_d3dformat(DepthStencilFormat), auxBuffers, numSamples, pbuffer, findCompatible); + + if(!getColorBits(ColorFormat, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits)) { + ERR("Unable to get color bits for format %s (%#x)!\n", debug_d3dformat(ColorFormat), ColorFormat); + 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(DepthStencilFormat != WINED3DFMT_D24S8) + FIXME("Add OpenGL context recreation support to SetDepthStencilSurface\n"); + + DepthStencilFormat = WINED3DFMT_D24S8; + + if(DepthStencilFormat) { + getDepthStencilBits(DepthStencilFormat, &depthBits, &stencilBits); + } + + for(matchtry = 0; matchtry < (sizeof(matches) / sizeof(matches[0])) && !iPixelFormat; matchtry++) { + for(i=0; iadapter->cfgs[i]; + + /* For now only accept RGBA formats. Perhaps some day we will + * allow floating point formats for pbuffers. */ + if(cfgs->iPixelType != WGL_TYPE_RGBA_ARB) + continue; + + /* In window mode (!pbuffer) we need a window drawable format and double buffering. */ + if(!pbuffer && !(cfgs->windowDrawable && cfgs->doubleBuffer)) + continue; + + /* We like to have aux buffers in backbuffer mode */ + if(auxBuffers && !cfgs->auxBuffers && matches[matchtry].require_aux) + continue; + + /* In pbuffer-mode we need a pbuffer-capable format but we don't want double buffering */ + if(pbuffer && (!cfgs->pbufferDrawable || cfgs->doubleBuffer)) + continue; + + if(matches[matchtry].exact_color) { + if(cfgs->redSize != redBits) + continue; + if(cfgs->greenSize != greenBits) + continue; + if(cfgs->blueSize != blueBits) + continue; + } else { + if(cfgs->redSize < redBits) + continue; + if(cfgs->greenSize < greenBits) + continue; + if(cfgs->blueSize < blueBits) + continue; + } + if(matches[matchtry].exact_alpha) { + if(cfgs->alphaSize != alphaBits) + continue; + } else { + if(cfgs->alphaSize < alphaBits) + continue; + } + + /* We try to locate a format which matches our requirements exactly. In case of + * depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */ + if(cfgs->depthSize < depthBits) + continue; + else if(cfgs->depthSize > depthBits) + exactDepthMatch = FALSE; + + /* In all cases make sure the number of stencil bits matches our requirements + * even when we don't need stencil because it could affect performance EXCEPT + * on cards which don't offer depth formats without stencil like the i915 drivers + * on Linux. */ + if(stencilBits != cfgs->stencilSize && !(This->adapter->brokenStencil && stencilBits <= cfgs->stencilSize)) + continue; + + /* Check multisampling support */ + if(cfgs->numSamples != numSamples) + continue; + + /* When we have passed all the checks then we have found a format which matches our + * requirements. Note that we only check for a limit number of capabilities right now, + * so there can easily be a dozen of pixel formats which appear to be the 'same' but + * can still differ in things like multisampling, stereo, SRGB and other flags. + */ + + /* Exit the loop as we have found a format :) */ + if(exactDepthMatch) { + iPixelFormat = cfgs->iPixelFormat; + break; + } else if(!iPixelFormat) { + /* In the end we might end up with a format which doesn't exactly match our depth + * requirements. Accept the first format we found because formats with higher iPixelFormat + * values tend to have more extended capabilities (e.g. multisampling) which we don't need. */ + iPixelFormat = cfgs->iPixelFormat; + } + } + } + + /* When findCompatible is set and no suitable format was found, let ChoosePixelFormat choose a pixel format in order not to crash. */ + if(!iPixelFormat && !findCompatible) { + ERR("Can't find a suitable iPixelFormat\n"); + return FALSE; + } else if(!iPixelFormat) { + PIXELFORMATDESCRIPTOR pfd; + + TRACE("Falling back to ChoosePixelFormat as we weren't able to find an exactly matching pixel format\n"); + /* PixelFormat selection */ + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/ + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cAlphaBits = alphaBits; + pfd.cColorBits = colorBits; + pfd.cDepthBits = depthBits; + pfd.cStencilBits = stencilBits; + pfd.iLayerType = PFD_MAIN_PLANE; + + iPixelFormat = ChoosePixelFormat(hdc, &pfd); + if(!iPixelFormat) { + /* If this happens something is very wrong as ChoosePixelFormat barely fails */ + ERR("Can't find a suitable iPixelFormat\n"); + return FALSE; + } + } + + TRACE("Found iPixelFormat=%d for ColorFormat=%s, DepthStencilFormat=%s\n", iPixelFormat, debug_d3dformat(ColorFormat), debug_d3dformat(DepthStencilFormat)); + return iPixelFormat; +} + /***************************************************************************** * CreateContext * @@ -131,57 +595,28 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar TRACE("(%p): Creating a %s context for render target %p\n", This, create_pbuffer ? "offscreen" : "onscreen", target); -#define PUSH1(att) attribs[nAttribs++] = (att); -#define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value); if(create_pbuffer) { HDC hdc_parent = GetDC(win_handle); int iPixelFormat = 0; - short redBits, greenBits, blueBits, alphaBits, colorBits; - short depthBits, stencilBits; IWineD3DSurface *StencilSurface = This->stencilBufferTarget; WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0; - int attribs[256]; - int nAttribs = 0; - unsigned int nFormats; + /* Try to find a pixel format with pbuffer support. */ + iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffers */, 0 /* numSamples */, TRUE /* PBUFFER */, FALSE /* findCompatible */); + if(!iPixelFormat) { + TRACE("Trying to locate a compatible pixel format because an exact match failed.\n"); - /* Retrieve the specifications for the pixelformat from the backbuffer / stencilbuffer */ - getColorBits(target->resource.format, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits); - getDepthStencilBits(StencilBufferFormat, &depthBits, &stencilBits); - PUSH2(WGL_DRAW_TO_PBUFFER_ARB, 1); /* We need pbuffer support; doublebuffering isn't needed */ - PUSH2(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); /* Make sure we don't get a float or color index format */ - PUSH2(WGL_COLOR_BITS_ARB, colorBits); - PUSH2(WGL_RED_BITS_ARB, redBits); - PUSH2(WGL_GREEN_BITS_ARB, greenBits); - PUSH2(WGL_BLUE_BITS_ARB, blueBits); - PUSH2(WGL_ALPHA_BITS_ARB, alphaBits); - PUSH2(WGL_DEPTH_BITS_ARB, depthBits); - PUSH2(WGL_STENCIL_BITS_ARB, stencilBits); - PUSH1(0); /* end the list */ + /* 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, StencilBufferFormat, FALSE /* auxBuffer */, 0 /* numSamples */, TRUE /* PBUFFER */, TRUE /* findCompatible */); + } - /* Try to find a pixelformat that matches exactly. If that fails let ChoosePixelFormat try to find a close match */ - if(!GL_EXTCALL(wglChoosePixelFormatARB(hdc_parent, (const int*)&attribs, NULL, 1, &iPixelFormat, &nFormats))) - { - PIXELFORMATDESCRIPTOR pfd; - - TRACE("Falling back to ChoosePixelFormat as wglChoosePixelFormatARB failed\n"); - - ZeroMemory(&pfd, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER_DONTCARE | PFD_DRAW_TO_WINDOW; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = colorBits; - pfd.cDepthBits = depthBits; - pfd.cStencilBits = stencilBits; - pfd.iLayerType = PFD_MAIN_PLANE; - - iPixelFormat = ChoosePixelFormat(hdc_parent, &pfd); - if(!iPixelFormat) { - /* If this happens something is very wrong as ChoosePixelFormat barely fails */ - ERR("Can't find a suitable iPixelFormat for the pbuffer\n"); - } + /* 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; } TRACE("Creating a pBuffer drawable for the new context\n"); @@ -204,12 +639,11 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar } else { PIXELFORMATDESCRIPTOR pfd; int iPixelFormat; - short redBits, greenBits, blueBits, alphaBits, colorBits; - short depthBits=0, stencilBits=0; int res; - int attribs[256]; - int nAttribs = 0; - unsigned int nFormats; + WINED3DFORMAT ColorFormat = target->resource.format; + WINED3DFORMAT DepthStencilFormat = 0; + BOOL auxBuffers = FALSE; + int numSamples = 0; hdc = GetDC(win_handle); if(hdc == NULL) { @@ -217,78 +651,84 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar goto out; } - /* PixelFormat selection */ - PUSH2(WGL_DRAW_TO_WINDOW_ARB, GL_TRUE); /* We want to draw to a window */ - PUSH2(WGL_DOUBLE_BUFFER_ARB, GL_TRUE); - PUSH2(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); /* Make sure we don't get a float or color index format */ - PUSH2(WGL_SUPPORT_OPENGL_ARB, GL_TRUE); - PUSH2(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB); /* Make sure we receive an accelerated format. On windows (at least on ATI) this is not always the case */ + /* 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(!getColorBits(target->resource.format, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits)) { - ERR("Unable to get color bits for format %#x!\n", target->resource.format); - return FALSE; + if(target->resource.format == WINED3DFMT_X4R4G4B4) + ColorFormat = WINED3DFMT_A4R4G4B4; + else if(target->resource.format == WINED3DFMT_X8R8G8B8) + ColorFormat = WINED3DFMT_A8R8G8B8; } - PUSH2(WGL_COLOR_BITS_ARB, colorBits); - PUSH2(WGL_RED_BITS_ARB, redBits); - PUSH2(WGL_GREEN_BITS_ARB, greenBits); - PUSH2(WGL_BLUE_BITS_ARB, blueBits); - PUSH2(WGL_ALPHA_BITS_ARB, alphaBits); + + /* 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(ColorFormat == WINED3DFMT_P8) + ColorFormat = WINED3DFMT_A8R8G8B8; /* 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)); - if(!getDepthStencilBits(pPresentParms->AutoDepthStencilFormat, &depthBits, &stencilBits)) { - ERR("Unable to get depth / stencil bits for AutoDepthStencilFormat %#x!\n", pPresentParms->AutoDepthStencilFormat); - return FALSE; - } - PUSH2(WGL_DEPTH_BITS_ARB, depthBits); - PUSH2(WGL_STENCIL_BITS_ARB, stencilBits); + DepthStencilFormat = pPresentParms->AutoDepthStencilFormat; } - PUSH1(0); /* end the list */ - - /* In case of failure hope that standard ChooosePixelFormat will find something suitable */ - if(!GL_EXTCALL(wglChoosePixelFormatARB(hdc, (const int*)&attribs, NULL, 1, &iPixelFormat, &nFormats))) - { - /* PixelFormat selection */ - ZeroMemory(&pfd, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/ - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cAlphaBits = alphaBits; - pfd.cColorBits = colorBits; - pfd.cDepthBits = depthBits; - pfd.cStencilBits = stencilBits; - pfd.iLayerType = PFD_MAIN_PLANE; - - iPixelFormat = ChoosePixelFormat(hdc, &pfd); - if(!iPixelFormat) { - /* If this happens something is very wrong as ChoosePixelFormat barely fails */ - ERR("Can't find a suitable iPixelFormat\n"); + /* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD */ + if(pPresentParms->MultiSampleType && (pPresentParms->SwapEffect == WINED3DSWAPEFFECT_DISCARD)) { + if(!GL_SUPPORT(ARB_MULTISAMPLE)) + ERR("The program is requesting multisampling without support!\n"); + else { + ERR("Requesting MultiSampleType=%d\n", pPresentParms->MultiSampleType); + numSamples = pPresentParms->MultiSampleType; } } + /* Try to find a pixel format which matches our requirements */ + iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, numSamples, FALSE /* PBUFFER */, FALSE /* findCompatible */); + + /* 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, ColorFormat, DepthStencilFormat, auxBuffers, 0 /* numSamples */, FALSE /* PBUFFER */, TRUE /* findCompatible */ ); + } + + /* 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 FALSE; + } + DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd); res = SetPixelFormat(hdc, iPixelFormat, NULL); if(!res) { int oldPixelFormat = GetPixelFormat(hdc); - if(oldPixelFormat) { + /* 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. */ + + if(oldPixelFormat == iPixelFormat) { + /* We don't have to do anything as the formats are the same :) */ + } else if(oldPixelFormat && GL_SUPPORT(WGL_WINE_PIXEL_FORMAT_PASSTHROUGH)) { + res = GL_EXTCALL(wglSetPixelFormatWINE(hdc, iPixelFormat, NULL)); + + if(!res) { + ERR("wglSetPixelFormatWINE failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); + return FALSE; + } + } 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 { + } else { ERR("SetPixelFormat failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); return FALSE; } } } -#undef PUSH1 -#undef PUSH2 ctx = pwglCreateContext(hdc); if(This->numContexts) pwglShareLists(This->contexts[0]->glCtx, ctx); @@ -314,18 +754,38 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar ret->surface = (IWineD3DSurface *) target; ret->isPBuffer = create_pbuffer; ret->tid = GetCurrentThreadId(); + if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) { + /* Create the dirty constants array and initialize them to dirty */ + ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, + sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, + sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + memset(ret->vshader_const_dirty, 1, + sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + memset(ret->pshader_const_dirty, 1, + sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + } TRACE("Successfully created new context %p\n", ret); + list_init(&ret->fbo_list); + /* Set up the context defaults */ oldCtx = pwglGetCurrentContext(); oldDrawable = pwglGetCurrentDC(); + if(oldCtx && oldDrawable) { + /* See comment in ActivateContext context switching */ + This->frag_pipe->enable_extension((IWineD3DDevice *) This, FALSE); + } if(pwglMakeCurrent(hdc, ctx) == FALSE) { ERR("Cannot activate context to set up defaults\n"); goto out; } ENTER_GL(); + + glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers); + TRACE("Setting up the screen\n"); /* Clear the screen */ glClearColor(1.0, 0.0, 0.0, 0.0); @@ -372,9 +832,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)"); } if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glEnable(GL_TEXTURE_SHADER_NV); - checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); - /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d * the previous texture where to source the offset from is always unit - 1. */ @@ -384,6 +841,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...\n"); } } + if(GL_SUPPORT(ARB_POINT_SPRITE)) { for(s = 0; s < GL_LIMITS(textures); s++) { GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s)); @@ -393,12 +851,20 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar } LEAVE_GL(); + /* Never keep GL_FRAGMENT_SHADER_ATI enabled on a context that we switch away from, + * but enable it for the first context we create, and reenable it on the old context + */ if(oldDrawable && oldCtx) { pwglMakeCurrent(oldDrawable, oldCtx); + } else { + last_device = This; } + This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); + + return ret; out: - return ret; + return NULL; } /***************************************************************************** @@ -429,7 +895,8 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con ERR("Cannot allocate a new context array, PANIC!!!\n"); } t = 0; - for(s = 0; s < This->numContexts; s++) { + /* Note that we decreased numContexts a few lines up, so use '<=' instead of '<' */ + for(s = 0; s <= This->numContexts; s++) { if(oldArray[s] == context) continue; This->contexts[t] = oldArray[s]; t++; @@ -453,32 +920,65 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con * *****************************************************************************/ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) { + struct fbo_entry *entry, *entry2; - /* check that we are the current context first */ TRACE("Destroying ctx %p\n", context); - if(pwglGetCurrentContext() == context->glCtx){ - pwglMakeCurrent(NULL, NULL); + + /* The correct GL context needs to be active to cleanup the GL resources below */ + if(pwglGetCurrentContext() != context->glCtx){ + pwglMakeCurrent(context->hdc, context->glCtx); + last_device = NULL; } + ENTER_GL(); + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) { + context_destroy_fbo_entry(This, entry); + } + if (context->src_fbo) { + TRACE("Destroy src FBO %d\n", context->src_fbo); + context_destroy_fbo(This, &context->src_fbo); + } + if (context->dst_fbo) { + TRACE("Destroy dst FBO %d\n", context->dst_fbo); + context_destroy_fbo(This, &context->dst_fbo); + } + + LEAVE_GL(); + + /* Cleanup the GL context */ + pwglMakeCurrent(NULL, NULL); if(context->isPBuffer) { GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc)); GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer)); } else ReleaseDC(context->win_handle, context->hdc); pwglDeleteContext(context->glCtx); + HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty); + HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty); RemoveContextFromArray(This, context); } +static inline void set_blit_dimension(UINT width, UINT height) { + glMatrixMode(GL_PROJECTION); + checkGLcall("glMatrixMode(GL_PROJECTION)"); + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + glOrtho(0, width, height, 0, 0.0, -1.0); + checkGLcall("glOrtho"); + glViewport(0, 0, width, height); + checkGLcall("glViewport"); +} + /***************************************************************************** * SetupForBlit * * Sets up a context for DirectDraw blitting. - * All texture units are disabled, except unit 0 - * Texture unit 0 is activted where GL_TEXTURE_2D is activated - * fog, lighting, blending, alpha test, z test, scissor test, culling diabled + * All texture units are disabled, texture unit 0 is set as current unit + * fog, lighting, blending, alpha test, z test, scissor test, culling disabled * color writing enabled for all channels * register combiners disabled, shaders disabled - * world matris is set to identity, texture matrix 0 too + * world matrix is set to identity, texture matrix 0 too * projection matrix is setup for drawing screen coordinates * * Params: @@ -489,10 +989,19 @@ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) { * *****************************************************************************/ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *context, UINT width, UINT height) { - int i; + int i, sampler; + const struct StateEntry *StateTable = This->StateTable; TRACE("Setting up context %p for blitting\n", context); if(context->last_was_blit) { + if(context->blit_w != width || context->blit_h != height) { + set_blit_dimension(width, height); + context->blit_w = width; context->blit_h = height; + /* No need to dirtify here, the states are still dirtified because they weren't + * applied since the last SetupForBlit call. Otherwise last_was_blit would not + * be set + */ + } TRACE("Context is already set up for blitting, nothing to do\n"); return; } @@ -502,21 +1011,18 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex /* Disable shaders */ This->shader_backend->shader_cleanup((IWineD3DDevice *) This); - Context_MarkStateDirty(context, STATE_VSHADER); - Context_MarkStateDirty(context, STATE_PIXELSHADER); + Context_MarkStateDirty(context, STATE_VSHADER, StateTable); + Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable); /* Disable all textures. The caller can then bind a texture it wants to blit * from */ - if(GL_SUPPORT(NV_REGISTER_COMBINERS)) { - glDisable(GL_REGISTER_COMBINERS_NV); - checkGLcall("glDisable(GL_REGISTER_COMBINERS_NV)"); - } if (GL_SUPPORT(ARB_MULTITEXTURE)) { /* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed * function texture unit. No need to care for higher samplers */ for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) { + sampler = This->rev_tex_unit_map[i]; GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); checkGLcall("glActiveTextureARB"); @@ -526,26 +1032,41 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex } glDisable(GL_TEXTURE_3D); checkGLcall("glDisable GL_TEXTURE_3D"); + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB"); + } glDisable(GL_TEXTURE_2D); checkGLcall("glDisable GL_TEXTURE_2D"); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);"); - Context_MarkStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)); - Context_MarkStateDirty(context, STATE_SAMPLER(i)); + if (sampler != -1) { + if (sampler < MAX_TEXTURES) { + Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable); + } + Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable); + } } GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); checkGLcall("glActiveTextureARB"); } + + sampler = This->rev_tex_unit_map[0]; + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { glDisable(GL_TEXTURE_CUBE_MAP_ARB); checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB"); } glDisable(GL_TEXTURE_3D); checkGLcall("glDisable GL_TEXTURE_3D"); - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable GL_TEXTURE_2D"); + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB"); + } + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable GL_TEXTURE_2D"); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); @@ -553,7 +1074,6 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex checkGLcall("glMatrixMode(GL_TEXTURE)"); glLoadIdentity(); checkGLcall("glLoadIdentity()"); - Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0)); if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) { glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, @@ -561,67 +1081,63 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex 0.0); checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ..."); } - Context_MarkStateDirty(context, STATE_SAMPLER(0)); - Context_MarkStateDirty(context, STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)); + + if (sampler != -1) { + if (sampler < MAX_TEXTURES) { + Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + sampler), StateTable); + Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable); + } + Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable); + } /* Other misc states */ glDisable(GL_ALPHA_TEST); checkGLcall("glDisable(GL_ALPHA_TEST)"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHATESTENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHATESTENABLE), StateTable); glDisable(GL_LIGHTING); checkGLcall("glDisable GL_LIGHTING"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING), StateTable); glDisable(GL_DEPTH_TEST); checkGLcall("glDisable GL_DEPTH_TEST"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable); glDisable(GL_FOG); checkGLcall("glDisable GL_FOG"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable); glDisable(GL_BLEND); checkGLcall("glDisable GL_BLEND"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); glDisable(GL_CULL_FACE); checkGLcall("glDisable GL_CULL_FACE"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CULLMODE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CULLMODE), StateTable); glDisable(GL_STENCIL_TEST); checkGLcall("glDisable GL_STENCIL_TEST"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_STENCILENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_STENCILENABLE), StateTable); + glDisable(GL_SCISSOR_TEST); + checkGLcall("glDisable GL_SCISSOR_TEST"); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable); if(GL_SUPPORT(ARB_POINT_SPRITE)) { glDisable(GL_POINT_SPRITE_ARB); checkGLcall("glDisable GL_POINT_SPRITE_ARB"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_POINTSPRITEENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), StateTable); } glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); checkGLcall("glColorMask"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable); if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { glDisable(GL_COLOR_SUM_EXT); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE), StateTable); checkGLcall("glDisable(GL_COLOR_SUM_EXT)"); } - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB)); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE)); - checkGLcall("glFinalCombinerInputNV"); - } /* Setup transforms */ glMatrixMode(GL_MODELVIEW); checkGLcall("glMatrixMode(GL_MODELVIEW)"); glLoadIdentity(); checkGLcall("glLoadIdentity()"); - Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))); - - glMatrixMode(GL_PROJECTION); - checkGLcall("glMatrixMode(GL_PROJECTION)"); - glLoadIdentity(); - checkGLcall("glLoadIdentity()"); - glOrtho(0, width, height, 0, 0.0, -1.0); - checkGLcall("glOrtho"); - Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)); + Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), StateTable); context->last_was_rhw = TRUE; - Context_MarkStateDirty(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ + Context_MarkStateDirty(context, STATE_VDECL, StateTable); /* because of last_was_rhw = TRUE */ glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); @@ -629,16 +1145,15 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING)); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable); - glViewport(0, 0, width, height); - checkGLcall("glViewport"); - Context_MarkStateDirty(context, STATE_VIEWPORT); + set_blit_dimension(width, height); + context->blit_w = width; context->blit_h = height; + Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable); + Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable); - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glDisable(GL_TEXTURE_SHADER_NV); - checkGLcall("glDisable(GL_TEXTURE_SHADER_NV)"); - } + + This->frag_pipe->enable_extension((IWineD3DDevice *) This, FALSE); } /***************************************************************************** @@ -674,12 +1189,29 @@ static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchai * Returns: The needed context * *****************************************************************************/ -static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid, GLint *buffer) { +static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid) { IWineD3DSwapChain *swapchain = NULL; HRESULT hr; BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen; WineD3DContext *context = This->activeContext; BOOL oldRenderOffscreen = This->render_offscreen; + const WINED3DFORMAT oldFmt = ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->resource.format; + const WINED3DFORMAT newFmt = ((IWineD3DSurfaceImpl *) target)->resource.format; + const struct StateEntry *StateTable = This->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(oldFmt != newFmt) { + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *old = getFormatDescEntry(oldFmt, NULL, NULL); + const StaticPixelFormatDesc *new = getFormatDescEntry(newFmt, &GLINFO_LOCATION, &glDesc); + + /* Disable blending when the alphaMask has changed and when a format doesn't support blending */ + if((old->alphaMask && !new->alphaMask) || (!old->alphaMask && new->alphaMask) || !(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) { + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + } + } hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **) &swapchain); if(hr == WINED3D_OK && swapchain) { @@ -693,11 +1225,6 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf * rendering. No context change is needed in that case */ - if(((IWineD3DSwapChainImpl *) swapchain)->frontBuffer == target) { - *buffer = GL_FRONT; - } else { - *buffer = GL_BACK; - } if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) { if(This->pbufferContext && tid == This->pbufferContext->tid) { This->pbufferContext->tid = 0; @@ -706,17 +1233,16 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf IWineD3DSwapChain_Release(swapchain); if(oldRenderOffscreen) { - Context_MarkStateDirty(context, WINED3DTS_PROJECTION); - Context_MarkStateDirty(context, STATE_VDECL); - Context_MarkStateDirty(context, STATE_VIEWPORT); - Context_MarkStateDirty(context, STATE_SCISSORRECT); - Context_MarkStateDirty(context, STATE_FRONTFACE); + Context_MarkStateDirty(context, 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); } } else { TRACE("Rendering offscreen\n"); This->render_offscreen = TRUE; - *buffer = This->offscreenBuffer; switch(wined3d_settings.offscreen_rendering_mode) { case ORM_FBO: @@ -724,7 +1250,7 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf if(This->activeContext && tid == This->lastThread) { context = This->activeContext; } else { - /* This may happen if the app jumps streight into offscreen rendering + /* 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. * @@ -773,7 +1299,7 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf if(This->activeContext && tid == This->lastThread) { context = This->activeContext; } else { - /* This may happen if the app jumps streight into offscreen rendering + /* 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. * @@ -785,22 +1311,42 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf break; } - if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) { - /* Make sure we have a OpenGL texture name so the PreLoad() used to read the buffer - * back when we are done won't mark us dirty. - */ - IWineD3DSurface_PreLoad(target); - } - if(!oldRenderOffscreen) { - Context_MarkStateDirty(context, WINED3DTS_PROJECTION); - Context_MarkStateDirty(context, STATE_VDECL); - Context_MarkStateDirty(context, STATE_VIEWPORT); - Context_MarkStateDirty(context, STATE_SCISSORRECT); - Context_MarkStateDirty(context, STATE_FRONTFACE); + Context_MarkStateDirty(context, 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); } } - if (readTexture) { + + /* 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. This leads to these possible situations: + * + * 0) lastActiveRenderTarget == target && oldTid == newTid: + * Nothing to do, we don't even reach this code in this case... + * + * 1) lastActiveRenderTarget != target && oldTid == newTid: + * The currently active context is OK for readback. Call PreLoad, and it + * performs the read + * + * 2) lastActiveRenderTarget == target && oldTid != newTid: + * Nothing to do - the drawable is unchanged + * + * 3) lastActiveRenderTarget != target && oldTid != newTid: + * This is tricky. We have to get a context with the old drawable from somewhere + * before we can switch to the new context. In this case, PreLoad calls + * ActivateContext(lastActiveRenderTarget) from the new(current) thread. This + * is case (2) then. The old drawable is activated for the new thread, and the + * readback can be done. The recursed ActivateContext does *not* call PreLoad again. + * After that, the outer ActivateContext(which calls PreLoad) can activate the new + * target for the new thread + */ + if (readTexture && This->lastActiveRenderTarget != target) { BOOL oldInDraw = This->isInDraw; /* PreLoad requires a context to load the texture, thus it will call ActivateContext. @@ -820,12 +1366,50 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf This->isInDraw = oldInDraw; } - if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) { - This->depth_copy_state = WINED3D_DCS_COPY; - } return context; } +static void apply_draw_buffer(IWineD3DDeviceImpl *This, IWineD3DSurface *target, BOOL blit) +{ + HRESULT hr; + IWineD3DSwapChain *swapchain; + + hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain); + if (SUCCEEDED(hr)) + { + IWineD3DSwapChain_Release((IUnknown *)swapchain); + glDrawBuffer(surface_get_gl_buffer(target, swapchain)); + checkGLcall("glDrawBuffers()"); + } + else + { + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + if (!blit) + { + if (GL_SUPPORT(ARB_DRAW_BUFFERS)) + { + GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers)); + checkGLcall("glDrawBuffers()"); + } + else + { + glDrawBuffer(This->draw_buffers[0]); + checkGLcall("glDrawBuffer()"); + } + } else { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + checkGLcall("glDrawBuffer()"); + } + } + else + { + glDrawBuffer(This->offscreenBuffer); + checkGLcall("glDrawBuffer()"); + } + } +} + /***************************************************************************** * ActivateContext * @@ -845,11 +1429,12 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU DWORD dirtyState, idx; BYTE shift; WineD3DContext *context; - GLint drawBuffer=0; + const struct StateEntry *StateTable = This->StateTable; TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid); if(This->lastActiveRenderTarget != target || tid != This->lastThread) { - context = FindContext(This, target, tid, &drawBuffer); + context = FindContext(This, target, tid); + context->draw_buffer_dirty = TRUE; This->lastActiveRenderTarget = target; This->lastThread = tid; } else { @@ -858,7 +1443,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU } /* Activate the opengl context */ - if(context != This->activeContext) { + if(last_device != This || context != This->activeContext) { BOOL ret; /* Prevent an unneeded context switch as those are expensive */ @@ -867,23 +1452,66 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU } else { TRACE("Switching gl ctx to %p, hdc=%p ctx=%p\n", context, context->hdc, context->glCtx); + + This->frag_pipe->enable_extension((IWineD3DDevice *) This, FALSE); ret = pwglMakeCurrent(context->hdc, context->glCtx); if(ret == FALSE) { ERR("Failed to activate the new context\n"); + } else if(!context->last_was_blit) { + This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); } } + if(This->activeContext->vshader_const_dirty) { + memset(This->activeContext->vshader_const_dirty, 1, + sizeof(*This->activeContext->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + } + if(This->activeContext->pshader_const_dirty) { + memset(This->activeContext->pshader_const_dirty, 1, + sizeof(*This->activeContext->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + } This->activeContext = context; + last_device = This; } /* We only need ENTER_GL for the gl calls made below and for the helper functions which make GL calls */ ENTER_GL(); - /* Select the right draw buffer. It is selected in FindContext. */ - if(drawBuffer && context->last_draw_buffer != drawBuffer) { - TRACE("Drawing to buffer: %#x\n", drawBuffer); - context->last_draw_buffer = drawBuffer; - glDrawBuffer(drawBuffer); - checkGLcall("glDrawBuffer"); + switch (usage) { + case CTXUSAGE_CLEAR: + case CTXUSAGE_DRAWPRIM: + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + context_apply_fbo_state((IWineD3DDevice *)This); + } + if (context->draw_buffer_dirty) { + apply_draw_buffer(This, target, FALSE); + context->draw_buffer_dirty = FALSE; + } + break; + + case CTXUSAGE_BLIT: + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + if (This->render_offscreen) { + FIXME("Activating for CTXUSAGE_BLIT for an offscreen target with ORM_FBO. This should be avoided.\n"); + context_bind_fbo((IWineD3DDevice *)This, GL_FRAMEBUFFER_EXT, &context->dst_fbo); + context_attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, target); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT"); + } else { + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT"); + } + context->draw_buffer_dirty = TRUE; + } + if (context->draw_buffer_dirty) { + apply_draw_buffer(This, target, TRUE); + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) { + context->draw_buffer_dirty = FALSE; + } + } + break; + + default: + break; } switch(usage) { @@ -892,23 +1520,27 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU break; case CTXUSAGE_CLEAR: - if(context->last_was_blit && GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glEnable(GL_TEXTURE_SHADER_NV); - checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); + if(context->last_was_blit) { + This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); } + /* Blending and clearing should be orthogonal, but tests on the nvidia driver show that disabling + * blending when clearing improves the clearing performance incredibly. + */ + glDisable(GL_BLEND); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + glEnable(GL_SCISSOR_TEST); checkGLcall("glEnable GL_SCISSOR_TEST"); context->last_was_blit = FALSE; - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); - Context_MarkStateDirty(context, STATE_SCISSORRECT); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable); + Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable); break; case CTXUSAGE_DRAWPRIM: /* This needs all dirty states applied */ - if(context->last_was_blit && GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glEnable(GL_TEXTURE_SHADER_NV); - checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); + if(context->last_was_blit) { + This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); } IWineD3DDeviceImpl_FindTexUnitMap(This); diff --git a/reactos/dll/directx/wine/wined3d/cubetexture.c b/reactos/dll/directx/wine/wined3d/cubetexture.c index e2d90999489..d84dcbcdfb1 100644 --- a/reactos/dll/directx/wine/wined3d/cubetexture.c +++ b/reactos/dll/directx/wine/wined3d/cubetexture.c @@ -4,6 +4,7 @@ * Copyright 2002-2005 Jason Edmeades * Copyright 2002-2005 Raphael Junqueira * Copyright 2005 Oliver Stieber + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,7 +24,7 @@ #include "config.h" #include "wined3d_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info static const GLenum cube_targets[6] = { @@ -46,7 +47,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_QueryInterface(IWineD3DCubeTexture || IsEqualGUID(riid, &IID_IWineD3DBase) || IsEqualGUID(riid, &IID_IWineD3DResource) || IsEqualGUID(riid, &IID_IWineD3DBaseTexture) - || IsEqualGUID(riid, &IID_IWineD3DTexture)) { + || IsEqualGUID(riid, &IID_IWineD3DCubeTexture)) { IUnknown_AddRef(iface); *ppobj = This; return S_OK; @@ -102,7 +103,6 @@ static DWORD WINAPI IWineD3DCubeTextureImpl_GetPriority(IWineD3DCubeTexture *ifa static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { /* Override the IWineD3DResource Preload method */ unsigned int i,j; - BOOL setGlTextureDesc = FALSE; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; BOOL srgb_mode = This->baseTexture.is_srgb; @@ -110,8 +110,6 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { TRACE("(%p) : About to load texture: dirtified(%d)\n", This, This->baseTexture.dirty); - if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE; - /* We only have to activate a context for gl when we're not drawing. In most cases PreLoad will be called during draw * and a context was activated at the beginning of drawPrimitive */ @@ -125,15 +123,24 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { srgb_was_toggled = (This->baseTexture.is_srgb != srgb_mode); This->baseTexture.is_srgb = srgb_mode; } - IWineD3DCubeTexture_BindTexture(iface); - ENTER_GL(); + if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { + for (i = 0; i < This->baseTexture.levels; i++) { + for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { + 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); + } + } + } + } /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */ if (This->baseTexture.dirty) { for (i = 0; i < This->baseTexture.levels; i++) { for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { - if(setGlTextureDesc) - IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], This->baseTexture.textureName, cube_targets[j]); IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); } } @@ -156,13 +163,31 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { } else { TRACE("(%p) Texture not dirty, nothing to do\n" , iface); } - LEAVE_GL(); /* No longer dirty */ This->baseTexture.dirty = FALSE; return ; } +static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) { + unsigned int i, j; + IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; + TRACE("(%p)\n", This); + + /* 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]); + IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], 0, IWineD3DTexture_GetTextureDimensions(iface)); + } + } + + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); +} + static WINED3DRESOURCETYPE WINAPI IWineD3DCubeTextureImpl_GetType(IWineD3DCubeTexture *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -210,14 +235,22 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_GetDirty(IWineD3DCubeTexture *iface) static HRESULT WINAPI IWineD3DCubeTextureImpl_BindTexture(IWineD3DCubeTexture *iface) { IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - TRACE("(%p) : relay to BaseTexture\n", This); - return IWineD3DBaseTextureImpl_BindTexture((IWineD3DBaseTexture *)iface); -} + BOOL set_gl_texture_desc = This->baseTexture.textureName == 0; + HRESULT hr; -static HRESULT WINAPI IWineD3DCubeTextureImpl_UnBindTexture(IWineD3DCubeTexture *iface) { - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; TRACE("(%p) : relay to BaseTexture\n", This); - return IWineD3DBaseTextureImpl_UnBindTexture((IWineD3DBaseTexture *)iface); + + hr = IWineD3DBaseTextureImpl_BindTexture((IWineD3DBaseTexture *)iface); + 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) { + IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], This->baseTexture.textureName, cube_targets[j]); + } + } + } + + return hr; } static UINT WINAPI IWineD3DCubeTextureImpl_GetTextureDimensions(IWineD3DCubeTexture *iface){ @@ -227,6 +260,13 @@ static UINT WINAPI IWineD3DCubeTextureImpl_GetTextureDimensions(IWineD3DCubeText return GL_TEXTURE_CUBE_MAP_ARB; } +static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface) { + IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; + TRACE("(%p)\n", This); + + return FALSE; +} + static void WINAPI IWineD3DCubeTextureImpl_ApplyStateChanges(IWineD3DCubeTexture *iface, const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) { @@ -273,7 +313,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_GetCubeMapSurface(IWineD3DCubeText IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; HRESULT hr = WINED3DERR_INVALIDCALL; - if (Level < This->baseTexture.levels && FaceType >= WINED3DCUBEMAP_FACE_POSITIVE_X && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { + if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { *ppCubeMapSurface = This->surfaces[FaceType][Level]; IWineD3DSurface_AddRef(*ppCubeMapSurface); @@ -292,7 +332,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_LockRect(IWineD3DCubeTexture *ifac HRESULT hr = WINED3DERR_INVALIDCALL; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - if (Level < This->baseTexture.levels && FaceType >= WINED3DCUBEMAP_FACE_POSITIVE_X && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { + if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { hr = IWineD3DSurface_LockRect(This->surfaces[FaceType][Level], pLockedRect, pRect, Flags); } @@ -309,7 +349,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_UnlockRect(IWineD3DCubeTexture *if HRESULT hr = WINED3DERR_INVALIDCALL; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - if (Level < This->baseTexture.levels && FaceType >= WINED3DCUBEMAP_FACE_POSITIVE_X && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { + if (Level < This->baseTexture.levels && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { hr = IWineD3DSurface_UnlockRect(This->surfaces[FaceType][Level]); } @@ -326,7 +366,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_AddDirtyRect(IWineD3DCubeTexture IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; This->baseTexture.dirty = TRUE; TRACE("(%p) : dirtyfication of faceType(%d) Level (0)\n", This, FaceType); - if (FaceType >= WINED3DCUBEMAP_FACE_POSITIVE_X && FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { + if (FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) { hr = IWineD3DSurface_AddDirtyRect(This->surfaces[FaceType][0], pDirtyRect); } else { WARN("(%p) overflow FaceType(%d)\n", This, FaceType); @@ -350,6 +390,7 @@ const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl = IWineD3DCubeTextureImpl_SetPriority, IWineD3DCubeTextureImpl_GetPriority, IWineD3DCubeTextureImpl_PreLoad, + IWineD3DCubeTextureImpl_UnLoad, IWineD3DCubeTextureImpl_GetType, /* IWineD3DBaseTexture */ IWineD3DCubeTextureImpl_SetLOD, @@ -361,8 +402,8 @@ const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl = IWineD3DCubeTextureImpl_SetDirty, IWineD3DCubeTextureImpl_GetDirty, IWineD3DCubeTextureImpl_BindTexture, - IWineD3DCubeTextureImpl_UnBindTexture, IWineD3DCubeTextureImpl_GetTextureDimensions, + IWineD3DCubeTextureImpl_IsCondNP2, IWineD3DCubeTextureImpl_ApplyStateChanges, /* IWineD3DCubeTexture */ IWineD3DCubeTextureImpl_Destroy, diff --git a/reactos/dll/directx/wine/wined3d/device.c b/reactos/dll/directx/wine/wined3d/device.c index 30ac0b79d41..4ca96e655fa 100644 --- a/reactos/dll/directx/wine/wined3d/device.c +++ b/reactos/dll/directx/wine/wined3d/device.c @@ -6,8 +6,8 @@ * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber - * Copyright 2006-2007 Stefan Dösinger for CodeWeavers - * Copyright 2006-2007 Henri Verbeet + * Copyright 2006-2008 Stefan Dösinger for CodeWeavers + * Copyright 2006-2008 Henri Verbeet * Copyright 2007 Andrew Riedi * * This library is free software; you can redistribute it and/or @@ -163,18 +163,6 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { TRACE("(%p) : Releasing from %d\n", This, refCount + 1); if (!refCount) { - if (This->fbo) { - GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo)); - } - if (This->src_fbo) { - GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo)); - } - if (This->dst_fbo) { - GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo)); - } - - if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup); - /* TODO: Clean up all the surfaces and textures! */ /* NOTE: You must release the parent if the object was created via a callback ** ***************************/ @@ -207,90 +195,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnkno return WINED3D_OK; } -static void CreateVBO(IWineD3DVertexBufferImpl *object) { - IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */ - GLenum error, glUsage; - DWORD vboUsage = object->resource.usage; - if(object->Flags & VBFLAG_VBOCREATEFAIL) { - WARN("Creating a vbo failed once, not trying again\n"); - return; - } - - TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage)); - - /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */ - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - - /* Make sure that the gl error is cleared. Do not use checkGLcall - * here because checkGLcall just prints a fixme and continues. However, - * if an error during VBO creation occurs we can fall back to non-vbo operation - * with full functionality(but performance loss) - */ - while(glGetError() != GL_NO_ERROR); - - /* Basically the FVF parameter passed to CreateVertexBuffer is no good - * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with - * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer - * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified - * to check if the rhw and color values are in the correct format. - */ - - GL_EXTCALL(glGenBuffersARB(1, &object->vbo)); - error = glGetError(); - if(object->vbo == 0 || error != GL_NO_ERROR) { - WARN("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo)); - error = glGetError(); - if(error != GL_NO_ERROR) { - WARN("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - - /* Don't use static, because dx apps tend to update the buffer - * quite often even if they specify 0 usage. Because we always keep the local copy - * we never read from the vbo and can create a write only opengl buffer. - */ - switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) { - case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC: - case WINED3DUSAGE_DYNAMIC: - TRACE("Gl usage = GL_STREAM_DRAW\n"); - glUsage = GL_STREAM_DRAW_ARB; - break; - case WINED3DUSAGE_WRITEONLY: - default: - TRACE("Gl usage = GL_DYNAMIC_DRAW\n"); - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - } - - /* Reserve memory for the buffer. The amount of data won't change - * so we are safe with calling glBufferData once with a NULL ptr and - * calling glBufferSubData on updates - */ - GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage)); - error = glGetError(); - if(error != GL_NO_ERROR) { - WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - - LEAVE_GL(); - - return; - error: - /* Clean up all vbo init, but continue because we can work without a vbo :-) */ - FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n"); - if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo)); - object->vbo = 0; - object->Flags |= VBFLAG_VBOCREATEFAIL; - LEAVE_GL(); - return; -} - static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle, IUnknown *parent) { @@ -306,7 +210,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac return WINED3DERR_INVALIDCALL; } else if(Pool == WINED3DPOOL_SCRATCH) { /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense - * anyway, SCRATCH vertex buffers aren't useable anywhere + * anyway, SCRATCH vertex buffers aren't usable anywhere */ WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n"); *ppVertexBuffer = NULL; @@ -315,7 +219,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size) - TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object); + TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object); *ppVertexBuffer = (IWineD3DVertexBuffer *)object; object->fvf = FVF; @@ -336,9 +240,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac * more. In this call we can convert dx7 buffers too. */ conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR)); - if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && - (dxVersion > 7 || !conv) ) { - CreateVBO(object); + if(!GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { + TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n"); + } else if(Pool == WINED3DPOOL_SYSTEMMEM) { + TRACE("Not creating a vbo because the vertex buffer is in system memory\n"); + } else if(Usage & WINED3DUSAGE_DYNAMIC) { + TRACE("Not creating a vbo because the buffer has dynamic usage\n"); + } else if(dxVersion <= 7 && conv) { + TRACE("Not creating a vbo because dxVersion is 7 and the fvf needs conversion\n"); + } else { + object->Flags |= VBFLAG_CREATEVBO; } return WINED3D_OK; } @@ -538,11 +449,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, object->changed.pixelShader = TRUE; /* Pixel Shader Constants */ - for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) { + for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) { object->contained_ps_consts_f[i] = i; object->changed.pixelShaderConstantsF[i] = TRUE; } - object->num_contained_ps_consts_f = GL_LIMITS(vshader_constantsF); + object->num_contained_ps_consts_f = GL_LIMITS(pshader_constantsF); for (i = 0; i < MAX_CONST_B; ++i) { object->contained_ps_consts_b[i] = i; object->changed.pixelShaderConstantsB[i] = TRUE; @@ -675,7 +586,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */ unsigned int Size = 1; - const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, NULL, NULL); + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); + UINT mul_4w, mul_4h; TRACE("(%p) Create surface\n",This); /** FIXME: Check ranges on the inputs are valid @@ -700,11 +613,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG. ***************************/ - if(MultisampleQuality < 0) { - FIXME("Invalid multisample level %d\n", MultisampleQuality); - return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */ - } - if(MultisampleQuality > 0) { FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality); MultisampleQuality=0; @@ -718,21 +626,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U * it is based around 4x4 pixel blocks it requires padding, so allocate enough * space! *********************************/ + mul_4w = (Width + 3) & ~3; + mul_4h = (Height + 3) & ~3; if (WINED3DFMT_UNKNOWN == Format) { Size = 0; } else if (Format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */ - Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1; + Size = (mul_4w * tableEntry->bpp * mul_4h) >> 1; } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 || - Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) { - Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)); + Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5 || + Format == WINED3DFMT_ATI2N) { + Size = (mul_4w * tableEntry->bpp * mul_4h); } else { /* The pitch is a multiple of 4 bytes */ Size = ((Width * tableEntry->bpp) + This->surface_alignment - 1) & ~(This->surface_alignment - 1); - Size *= Height; + Size *= Height; } + if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale; + /** Create and initialise the surface resource **/ D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size) /* "Standalone" surface */ @@ -743,9 +656,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U object->currentDesc.MultiSampleType = MultiSample; object->currentDesc.MultiSampleQuality = MultisampleQuality; object->glDescription.level = Level; + object->heightscale = glDesc->heightscale != 0.0 ? glDesc->heightscale : 1.0; + list_init(&object->overlays); /* Flags */ - object->Flags = 0; + object->Flags = SFLAG_NORMCOORD; /* Default to normalized coords */ object->Flags |= Discard ? SFLAG_DISCARD : 0; object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0; object->Flags |= Lockable ? SFLAG_LOCKABLE : 0; @@ -800,10 +715,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U This, Width, Height, Format, debug_d3dformat(Format), (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size); - /* Store the DirectDraw primary surface. This is the first rendertarget surface created */ - if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) ) - This->ddraw_primary = (IWineD3DSurface *) object; - /* Look at the implementation and set the correct Vtable */ switch(Impl) { case SURFACE_OPENGL: @@ -850,12 +761,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U const GlPixelFormatDesc *glDesc; getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); - TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage); TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n", Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent); - /* TODO: It should only be possible to create textures for formats + /* TODO: It should only be possible to create textures for formats that are reported as supported */ if (WINED3DFMT_UNKNOWN >= Format) { WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This); @@ -867,6 +777,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U object->width = Width; object->height = Height; + if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) { + object->baseTexture.minMipLookup = &minMipLookup; + object->baseTexture.magLookup = &magLookup; + } else { + object->baseTexture.minMipLookup = &minMipLookup_noFilter; + object->baseTexture.magLookup = &magLookup_noFilter; + } + /** Non-power2 support **/ if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { pow2Width = Width; @@ -876,14 +794,54 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U pow2Width = pow2Height = 1; while (pow2Width < Width) pow2Width <<= 1; while (pow2Height < Height) pow2Height <<= 1; + + if(pow2Width != Width || pow2Height != Height) { + if(Levels > 1) { + WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n"); + HeapFree(GetProcessHeap(), 0, object); + *ppTexture = NULL; + return WINED3DERR_INVALIDCALL; + } else { + Levels = 1; + } + } } /** FIXME: add support for real non-power-two if it's provided by the video card **/ - /* Precalculated scaling for 'faked' non power of two texture coords */ - object->baseTexture.pow2Matrix[0] = (((float)Width) / ((float)pow2Width)); - object->baseTexture.pow2Matrix[5] = (((float)Height) / ((float)pow2Height)); - object->baseTexture.pow2Matrix[10] = 1.0; - object->baseTexture.pow2Matrix[15] = 1.0; + /* Precalculated scaling for 'faked' non power of two texture coords. + Second also 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. + */ + if(GL_SUPPORT(WINE_NORMALIZED_TEXRECT) && (Width != pow2Width || Height != pow2Height)) { + object->baseTexture.pow2Matrix[0] = 1.0; + object->baseTexture.pow2Matrix[5] = 1.0; + object->baseTexture.pow2Matrix[10] = 1.0; + object->baseTexture.pow2Matrix[15] = 1.0; + object->target = GL_TEXTURE_2D; + object->cond_np2 = TRUE; + pow2Width = Width; + pow2Height = Height; + object->baseTexture.minMipLookup = &minMipLookup_noFilter; + } else if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE) && + (Width != pow2Width || Height != pow2Height) && + !((Format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) && (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX))) + { + object->baseTexture.pow2Matrix[0] = (float)Width; + object->baseTexture.pow2Matrix[5] = (float)Height; + object->baseTexture.pow2Matrix[10] = 1.0; + object->baseTexture.pow2Matrix[15] = 1.0; + object->target = GL_TEXTURE_RECTANGLE_ARB; + object->cond_np2 = TRUE; + object->baseTexture.minMipLookup = &minMipLookup_noFilter; + } else { + object->baseTexture.pow2Matrix[0] = (((float)Width) / ((float)pow2Width)); + object->baseTexture.pow2Matrix[5] = (((float)Height) / ((float)pow2Height)); + object->baseTexture.pow2Matrix[10] = 1.0; + object->baseTexture.pow2Matrix[15] = 1.0; + object->target = GL_TEXTURE_2D; + object->cond_np2 = FALSE; + } TRACE(" xf(%f) yf(%f)\n", object->baseTexture.pow2Matrix[0], object->baseTexture.pow2Matrix[5]); /* Calculate levels for mip mapping */ @@ -984,6 +942,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa object->baseTexture.pow2Matrix[10] = 1.0; object->baseTexture.pow2Matrix[15] = 1.0; + if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) { + object->baseTexture.minMipLookup = &minMipLookup; + object->baseTexture.magLookup = &magLookup; + } else { + object->baseTexture.minMipLookup = &minMipLookup_noFilter; + object->baseTexture.magLookup = &magLookup_noFilter; + } + /* Calculate levels for mip mapping */ if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { @@ -1019,7 +985,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa HRESULT hr; /* Create the volume */ hr = D3DCB_CreateVolume(This->parent, parent, tmpW, tmpH, tmpD, Format, Pool, Usage, - (IWineD3DVolume **)&object->volumes[i], pSharedHandle); + &object->volumes[i], pSharedHandle); if(FAILED(hr)) { ERR("Creating a volume for the volume texture failed(%08x)\n", hr); @@ -1031,7 +997,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa /* Set its container to this object */ IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object); - /* calcualte the next mipmap level */ + /* calculate the next mipmap level */ tmpW = max(1, tmpW >> 1); tmpH = max(1, tmpH >> 1); tmpD = max(1, tmpD >> 1); @@ -1125,6 +1091,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface object->baseTexture.pow2Matrix[10] = ((float)EdgeLength) / ((float)pow2EdgeLength); object->baseTexture.pow2Matrix[15] = 1.0; + if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) { + object->baseTexture.minMipLookup = &minMipLookup; + object->baseTexture.magLookup = &magLookup; + } else { + object->baseTexture.minMipLookup = &minMipLookup_noFilter; + object->baseTexture.magLookup = &magLookup_noFilter; + } + /* Calculate levels for mip mapping */ if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { @@ -1196,6 +1170,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */ HRESULT hr = WINED3DERR_NOTAVAILABLE; + const IWineD3DQueryVtbl *vtable; /* Just a check to see if we support this type of query */ switch(Type) { @@ -1205,6 +1180,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE hr = WINED3D_OK; else WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n"); + + vtable = &IWineD3DOcclusionQuery_Vtbl; break; case WINED3DQUERYTYPE_EVENT: @@ -1214,6 +1191,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE */ FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This); } + vtable = &IWineD3DEventQuery_Vtbl; hr = WINED3D_OK; break; @@ -1230,6 +1208,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE case WINED3DQUERYTYPE_BANDWIDTHTIMINGS: case WINED3DQUERYTYPE_CACHEUTILIZATION: default: + /* Use the base Query vtable until we have a special one for each query */ + vtable = &IWineD3DQuery_Vtbl; FIXME("(%p) Unhandled query type %d\n", This, Type); } if(NULL == ppQuery || hr != WINED3D_OK) { @@ -1237,7 +1217,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE } D3DCREATEOBJECTINSTANCE(object, Query) + object->lpVtbl = vtable; object->type = Type; + object->state = QUERY_CREATED; /* allocated the 'extended' data based on the type of query requested */ switch(Type){ case WINED3DQUERYTYPE_OCCLUSION: @@ -1293,7 +1275,28 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE * window: Window to setup * *****************************************************************************/ -static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) { +static LONG fullscreen_style(LONG orig_style) { + LONG style = orig_style; + style &= ~WS_CAPTION; + style &= ~WS_THICKFRAME; + + /* Make sure the window is managed, otherwise we won't get keyboard input */ + style |= WS_POPUP | WS_SYSMENU; + + return style; +} + +static LONG fullscreen_exStyle(LONG orig_exStyle) { + LONG exStyle = orig_exStyle; + + /* Filter out window decorations */ + exStyle &= ~WS_EX_WINDOWEDGE; + exStyle &= ~WS_EX_CLIENTEDGE; + + return exStyle; +} + +static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window, UINT w, UINT h) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; LONG style, exStyle; @@ -1312,14 +1315,8 @@ static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *ifac This->style = style; This->exStyle = exStyle; - /* Filter out window decorations */ - style &= ~WS_CAPTION; - style &= ~WS_THICKFRAME; - exStyle &= ~WS_EX_WINDOWEDGE; - exStyle &= ~WS_EX_CLIENTEDGE; - - /* Make sure the window is managed, otherwise we won't get keyboard input */ - style |= WS_POPUP | WS_SYSMENU; + style = fullscreen_style(style); + exStyle = fullscreen_exStyle(exStyle); TRACE("Old style was %08x,%08x, setting to %08x,%08x\n", This->style, This->exStyle, style, exStyle); @@ -1329,8 +1326,7 @@ static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *ifac /* Inform the window about the update. */ SetWindowPos(window, HWND_TOP, 0, 0, - This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED); - ShowWindow(window, SW_NORMAL); + w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW); } /***************************************************************************** @@ -1346,6 +1342,7 @@ static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *ifac *****************************************************************************/ static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + LONG style, exStyle; /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL * switch, do nothing @@ -1355,8 +1352,18 @@ static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n", This, window, This->style, This->exStyle); - SetWindowLongW(window, GWL_STYLE, This->style); - SetWindowLongW(window, GWL_EXSTYLE, This->exStyle); + style = GetWindowLongW(window, GWL_STYLE); + exStyle = GetWindowLongW(window, GWL_EXSTYLE); + + /* Only restore the style if the application didn't modify it during the fullscreen phase. + * Some applications change it before calling Reset() when switching between windowed and + * fullscreen modes(HL2), some depend on the original style(Eve Online) + */ + if(style == fullscreen_style(This->style) && + exStyle == fullscreen_style(This->exStyle)) { + SetWindowLongW(window, GWL_STYLE, This->style); + SetWindowLongW(window, GWL_EXSTYLE, This->exStyle); + } /* Delete the old values */ This->style = 0; @@ -1372,7 +1379,8 @@ static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain, IUnknown* parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget, - D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) { + D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil, + WINED3DSURFTYPE surface_type) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; HDC hDc; @@ -1380,8 +1388,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic HRESULT hr = WINED3D_OK; IUnknown *bufferParent; BOOL displaymode_set = FALSE; + WINED3DDISPLAYMODE Mode; + const StaticPixelFormatDesc *formatDesc; - TRACE("(%p) : Created Aditional Swap Chain\n", This); + TRACE("(%p) : Created Additional Swap Chain\n", This); /** FIXME: Test under windows to find out what the life cycle of a swap chain is, * does a device hold a reference to a swap chain giving them a lifetime of the device @@ -1397,6 +1407,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic } D3DCREATEOBJECTINSTANCE(object, SwapChain) + switch(surface_type) { + case SURFACE_GDI: + object->lpVtbl = &IWineGDISwapChain_Vtbl; + break; + case SURFACE_OPENGL: + object->lpVtbl = &IWineD3DSwapChain_Vtbl; + break; + case SURFACE_UNKNOWN: + FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n"); + return WINED3DERR_INVALIDCALL; + } /********************* * Lookup the window Handle and the relating X window handle @@ -1407,7 +1428,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic if (!object->win_handle) { object->win_handle = This->createParms.hFocusWindow; } - if(!This->ddraw_window) IWineD3DDevice_SetHWND(iface, object->win_handle); + if(!pPresentationParameters->Windowed && object->win_handle) { + IWineD3DDeviceImpl_SetupFullscreenWindow(iface, object->win_handle, + pPresentationParameters->BackBufferWidth, + pPresentationParameters->BackBufferHeight); + } hDc = GetDC(object->win_handle); TRACE("Using hDc %p\n", hDc); @@ -1417,10 +1442,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic return WINED3DERR_NOTAVAILABLE; } - object->orig_width = GetSystemMetrics(SM_CXSCREEN); - object->orig_height = GetSystemMetrics(SM_CYSCREEN); - object->orig_fmt = pixelformat_for_depth(GetDeviceCaps(hDc, BITSPIXEL) * GetDeviceCaps(hDc, PLANES)); - ReleaseDC(object->win_handle, hDc); + /* Get info on the current display setup */ + IWineD3D_GetAdapterDisplayMode(This->wineD3D, This->adapter->num, &Mode); + object->orig_width = Mode.Width; + object->orig_height = Mode.Height; + object->orig_fmt = Mode.Format; + formatDesc = getFormatDescEntry(Mode.Format, NULL, NULL); /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero, * then the corresponding dimension of the client area of the hDeviceWindow @@ -1454,7 +1481,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic object->presentParms = *pPresentationParameters; TRACE("calling rendertarget CB\n"); - hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent, + hr = D3DCB_CreateRenderTarget(This->parent, parent, object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, @@ -1465,8 +1492,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic &object->frontBuffer, NULL /* pShared (always null)*/); if (object->frontBuffer != NULL) { - IWineD3DSurface_ModifyLocation(object->frontBuffer, SFLAG_INDRAWABLE, TRUE); IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object); + if(surface_type == SURFACE_OPENGL) { + IWineD3DSurface_ModifyLocation(object->frontBuffer, SFLAG_INDRAWABLE, TRUE); + } } else { ERR("Failed to create the front buffer\n"); goto error; @@ -1483,37 +1512,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic **************************************/ if (!pPresentationParameters->Windowed) { + WINED3DDISPLAYMODE mode; - DEVMODEW devmode; - HDC hdc; - int bpp = 0; - RECT clip_rc; - - /* Get info on the current display setup */ - hdc = GetDC(0); - bpp = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(0, hdc); /* Change the display settings */ - memset(&devmode, 0, sizeof(devmode)); - devmode.dmSize = sizeof(devmode); - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */ - devmode.dmPelsWidth = pPresentationParameters->BackBufferWidth; - devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight; - ChangeDisplaySettingsExW(This->adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL); + mode.Width = pPresentationParameters->BackBufferWidth; + mode.Height = pPresentationParameters->BackBufferHeight; + mode.Format = pPresentationParameters->BackBufferFormat; + mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz; + + IWineD3DDevice_SetDisplayMode(iface, 0, &mode); displaymode_set = TRUE; - - /* For GetDisplayMode */ - This->ddraw_width = devmode.dmPelsWidth; - This->ddraw_height = devmode.dmPelsHeight; - This->ddraw_format = pPresentationParameters->BackBufferFormat; - - IWineD3DDevice_SetFullscreen(iface, TRUE); - - /* And finally clip mouse to our screen */ - SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight); - ClipCursor(&clip_rc); } /** @@ -1530,14 +1539,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic return E_OUTOFMEMORY; object->num_contexts = 1; - object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, object->win_handle, FALSE /* pbuffer */, pPresentationParameters); - if (!object->context[0]) { - ERR("Failed to create a new context\n"); - hr = WINED3DERR_NOTAVAILABLE; - goto error; - } else { - TRACE("Context created (HWND=%p, glContext=%p)\n", - object->win_handle, object->context[0]->glCtx); + if(surface_type == SURFACE_OPENGL) { + object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, object->win_handle, FALSE /* pbuffer */, pPresentationParameters); + if (!object->context[0]) { + ERR("Failed to create a new context\n"); + hr = WINED3DERR_NOTAVAILABLE; + goto error; + } else { + TRACE("Context created (HWND=%p, glContext=%p)\n", + object->win_handle, object->context[0]->glCtx); + } } /********************* @@ -1555,7 +1566,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic for(i = 0; i < object->presentParms.BackBufferCount; i++) { TRACE("calling rendertarget CB\n"); - hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent, + hr = D3DCB_CreateRenderTarget(This->parent, parent, object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, @@ -1571,26 +1582,30 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic ERR("Cannot create new back buffer\n"); goto error; } - ENTER_GL(); - glDrawBuffer(GL_BACK); - checkGLcall("glDrawBuffer(GL_BACK)"); - LEAVE_GL(); + if(surface_type == SURFACE_OPENGL) { + ENTER_GL(); + glDrawBuffer(GL_BACK); + checkGLcall("glDrawBuffer(GL_BACK)"); + LEAVE_GL(); + } } } else { object->backBuffer = NULL; /* Single buffering - draw to front buffer */ - ENTER_GL(); - glDrawBuffer(GL_FRONT); - checkGLcall("glDrawBuffer(GL_FRONT)"); - LEAVE_GL(); + if(surface_type == SURFACE_OPENGL) { + ENTER_GL(); + glDrawBuffer(GL_FRONT); + checkGLcall("glDrawBuffer(GL_FRONT)"); + LEAVE_GL(); + } } /* Under directX swapchains share the depth stencil, so only create one depth-stencil */ - if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) { + if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK && surface_type == SURFACE_OPENGL) { TRACE("Creating depth stencil buffer\n"); if (This->auto_depth_stencil_buffer == NULL ) { - hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent, + hr = D3DCB_CreateDepthStencil(This->parent, parent, object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, @@ -1612,6 +1627,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic object->wantsDepthStencilBuffer = FALSE; } + IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain *) object, &object->orig_gamma); + TRACE("Created swapchain %p\n", object); TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer); return WINED3D_OK; @@ -1619,23 +1636,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic error: if (displaymode_set) { DEVMODEW devmode; - HDC hdc; - int bpp = 0; RECT clip_rc; SetRect(&clip_rc, 0, 0, object->orig_width, object->orig_height); ClipCursor(NULL); - /* Get info on the current display setup */ - hdc = GetDC(0); - bpp = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(0, hdc); - /* Change the display settings */ memset(&devmode, 0, sizeof(devmode)); devmode.dmSize = sizeof(devmode); devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */ + devmode.dmBitsPerPel = formatDesc->bpp * 8; devmode.dmPelsWidth = object->orig_width; devmode.dmPelsHeight = object->orig_height; ChangeDisplaySettingsExW(This->adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL); @@ -1696,7 +1706,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, U * Vertex Declaration *****/ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, - IUnknown *parent, const WINED3DVERTEXELEMENT *elements, size_t element_count) { + IUnknown *parent, const WINED3DVERTEXELEMENT *elements, UINT element_count) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexDeclarationImpl *object = NULL; HRESULT hr = WINED3D_OK; @@ -1707,11 +1717,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* D3DCREATEOBJECTINSTANCE(object, VertexDeclaration) hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count); + if(FAILED(hr)) { + *ppVertexDeclaration = NULL; + HeapFree(GetProcessHeap(), 0, object); + } return hr; } -static size_t ConvertFvfToDeclaration(DWORD fvf, WINED3DVERTEXELEMENT** ppVertexElements) { +static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */ + DWORD fvf, WINED3DVERTEXELEMENT** ppVertexElements) { unsigned int idx, idx2; unsigned int offset; @@ -1727,7 +1742,7 @@ static size_t ConvertFvfToDeclaration(DWORD fvf, WINED3DVERTEXELEMENT** ppVertex BOOL has_specular = (fvf & WINED3DFVF_SPECULAR) !=0; DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT; - DWORD texcoords = (fvf & 0x00FF0000) >> 16; + DWORD texcoords = (fvf & 0xFFFF0000) >> 16; WINED3DVERTEXELEMENT end_element = WINED3DDECL_END(); WINED3DVERTEXELEMENT *elements = NULL; @@ -1745,7 +1760,7 @@ static size_t ConvertFvfToDeclaration(DWORD fvf, WINED3DVERTEXELEMENT** ppVertex if (!elements) return 0; - memcpy(&elements[size-1], &end_element, sizeof(WINED3DVERTEXELEMENT)); + elements[size-1] = end_element; idx = 0; if (has_pos) { if (!has_blend && (fvf & WINED3DFVF_XYZRHW)) { @@ -1839,10 +1854,11 @@ static size_t ConvertFvfToDeclaration(DWORD fvf, WINED3DVERTEXELEMENT** ppVertex static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *Parent, DWORD Fvf) { WINED3DVERTEXELEMENT* elements = NULL; - size_t size; + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + unsigned int size; DWORD hr; - size = ConvertFvfToDeclaration(Fvf, &elements); + size = ConvertFvfToDeclaration(This, Fvf, &elements); if (size == 0) return WINED3DERR_OUTOFVIDEOMEMORY; hr = IWineD3DDevice_CreateVertexDeclaration(iface, ppVertexDeclaration, Parent, elements, size); @@ -1852,7 +1868,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3D return WINED3D_OK; } -/* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */ @@ -1873,6 +1888,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac IWineD3DVertexShader_Release(*ppVertexShader); return WINED3DERR_INVALIDCALL; } + list_add_head(&This->shaders, &object->baseShader.shader_list_entry); return WINED3D_OK; } @@ -1887,6 +1903,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction); if (WINED3D_OK == hr) { TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader); + list_add_head(&This->shaders, &object->baseShader.shader_list_entry); } else { WARN("(%p) : Failed to create pixel shader\n", This); } @@ -1989,14 +2006,64 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi return; } +static void create_dummy_textures(IWineD3DDeviceImpl *This) { + unsigned int i; + /* Under DirectX you can have texture stage operations even if no texture is + bound, whereas opengl will only do texture operations when a valid texture is + bound. We emulate this by creating dummy textures and binding them to each + texture stage, but disable all stages by default. Hence if a stage is enabled + then the default texture will kick in until replaced by a SetTexture call */ + ENTER_GL(); + + if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { + /* The dummy texture does not have client storage backing */ + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); + checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)"); + } + for (i = 0; i < GL_LIMITS(textures); i++) { + GLubyte white = 255; + + /* Make appropriate texture active */ + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); + } else if (i > 0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + } + + /* Generate an opengl texture name */ + glGenTextures(1, &This->dummyTextureName[i]); + checkGLcall("glGenTextures"); + TRACE("Dummy Texture %d given name %d\n", i, This->dummyTextureName[i]); + + /* Generate a dummy 2d texture (not using 1d because they cause many + * DRI drivers fall back to sw) */ + This->stateBlock->textureDimensions[i] = GL_TEXTURE_2D; + glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]); + checkGLcall("glBindTexture"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white); + checkGLcall("glTexImage2D"); + } + if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { + /* Reenable because if supported it is enabled by default */ + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)"); + } + + LEAVE_GL(); +} + static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - IWineD3DSwapChainImpl *swapchain; + IWineD3DSwapChainImpl *swapchain = NULL; HRESULT hr; DWORD state; + unsigned int i; TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain); if(This->d3d_initialized) return WINED3DERR_INVALIDCALL; + if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL; /* TODO: Test if OpenGL is compiled in and loaded */ @@ -2020,9 +2087,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR } This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); - This->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers)); + This->NumberOfPalettes = 1; + This->palettes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PALETTEENTRY*)); + if(!This->palettes || !This->render_targets || !This->draw_buffers) { + ERR("Out of memory!\n"); + goto err_out; + } + This->palettes[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256); + if(!This->palettes[0]) { + ERR("Out of memory!\n"); + goto err_out; + } + for (i = 0; i < 256; ++i) { + This->palettes[0][i].peRed = 0xFF; + This->palettes[0][i].peGreen = 0xFF; + This->palettes[0][i].peBlue = 0xFF; + This->palettes[0][i].peFlags = 0xFF; + } + This->currentPalette = 0; + /* Initialize the texture unit mapping to a 1:1 mapping */ for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state) { if (state < GL_LIMITS(fragment_samplers)) { @@ -2036,7 +2121,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR /* Setup the implicit swapchain */ TRACE("Creating implicit swapchain\n"); - hr=D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); + hr=D3DCB_CreateAdditionalSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); if (FAILED(hr) || !swapchain) { WARN("Failed to create implicit swapchain\n"); goto err_out; @@ -2070,14 +2155,29 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR IWineD3DSurface_AddRef(This->stencilBufferTarget); } + hr = This->shader_backend->shader_alloc_private(iface); + if(FAILED(hr)) { + TRACE("Shader private data couldn't be allocated\n"); + goto err_out; + } + hr = This->frag_pipe->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Fragment pipeline private data couldn't be allocated\n"); + goto err_out; + } + hr = This->blitter->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Blitter private data couldn't be allocated\n"); + goto err_out; + } + /* Set up some starting GL setup */ - ENTER_GL(); /* Setup all the devices defaults */ IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock); -#if 0 - IWineD3DImpl_CheckGraphicsMemory(); -#endif + create_dummy_textures(This); + + ENTER_GL(); { /* Set a default viewport */ WINED3DVIEWPORT vp; @@ -2104,7 +2204,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR case ORM_BACKBUFFER: { - if(GL_LIMITS(aux_buffers) > 0) { + if(This->activeContext->aux_buffers > 0) { TRACE("Using auxilliary buffer for offscreen rendering\n"); This->offscreenBuffer = GL_AUX0; } else { @@ -2127,22 +2227,63 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR if(wined3d_settings.logo) { IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo); } + This->highest_dirty_ps_const = 0; + This->highest_dirty_vs_const = 0; return WINED3D_OK; - err_out: +err_out: HeapFree(GetProcessHeap(), 0, This->render_targets); - HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments); HeapFree(GetProcessHeap(), 0, This->draw_buffers); HeapFree(GetProcessHeap(), 0, This->swapchains); This->NumberOfSwapChains = 0; + if(This->palettes) { + HeapFree(GetProcessHeap(), 0, This->palettes[0]); + HeapFree(GetProcessHeap(), 0, This->palettes); + } + This->NumberOfPalettes = 0; if(swapchain) { IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain); } - This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers)); if(This->stateBlock) { IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->stateBlock); This->stateBlock = NULL; } + if (This->blit_priv) { + This->blitter->free_private(iface); + } + if (This->fragment_priv) { + This->frag_pipe->free_private(iface); + } + if (This->shader_priv) { + This->shader_backend->shader_free_private(iface); + } + return hr; +} + +static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DSwapChainImpl *swapchain = NULL; + HRESULT hr; + + /* Setup the implicit swapchain */ + TRACE("Creating implicit swapchain\n"); + hr=D3DCB_CreateAdditionalSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); + if (FAILED(hr) || !swapchain) { + WARN("Failed to create implicit swapchain\n"); + goto err_out; + } + + This->NumberOfSwapChains = 1; + This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *)); + if(!This->swapchains) { + ERR("Out of memory!\n"); + goto err_out; + } + This->swapchains[0] = (IWineD3DSwapChain *) swapchain; + return WINED3D_OK; + +err_out: + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return hr; } @@ -2154,7 +2295,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL; - /* I don't think that the interface guarants that the device is destroyed from the same thread + /* 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 */ ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); @@ -2173,7 +2314,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D /* Delete the palette conversion shader if it is around */ if(This->paletteConversionShader) { + ENTER_GL(); GL_EXTCALL(glDeleteProgramsARB(1, &This->paletteConversionShader)); + LEAVE_GL(); This->paletteConversionShader = 0; } @@ -2195,6 +2338,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D IWineD3DDevice_SetTexture(iface, WINED3DVERTEXTEXTURESAMPLER0 + sampler, NULL); } + /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader + * private data, it might contain opengl pointers + */ + if(This->depth_blt_texture) { + glDeleteTextures(1, &This->depth_blt_texture); + This->depth_blt_texture = 0; + } + if (This->depth_blt_rb) { + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb)); + This->depth_blt_rb = 0; + This->depth_blt_rb_w = 0; + This->depth_blt_rb_h = 0; + } + /* Release the update stateblock */ if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){ if(This->updateStateBlock != This->stateBlock) @@ -2214,6 +2371,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D } } + /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */ + This->blitter->free_private(iface); + This->frag_pipe->free_private(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)){ @@ -2224,7 +2386,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D 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, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */ + /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */ } TRACE("Setting rendertarget to NULL\n"); This->render_targets[0] = NULL; @@ -2247,35 +2409,35 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D This->swapchains = NULL; This->NumberOfSwapChains = 0; + for (i = 0; i < This->NumberOfPalettes; i++) HeapFree(GetProcessHeap(), 0, This->palettes[i]); + HeapFree(GetProcessHeap(), 0, This->palettes); + This->palettes = NULL; + This->NumberOfPalettes = 0; + HeapFree(GetProcessHeap(), 0, This->render_targets); - HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments); HeapFree(GetProcessHeap(), 0, This->draw_buffers); This->render_targets = NULL; - This->fbo_color_attachments = NULL; This->draw_buffers = NULL; - This->d3d_initialized = FALSE; return WINED3D_OK; } -static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) { +static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false"); + unsigned int i; - /* Setup the window for fullscreen mode */ - if(fullscreen && !This->ddraw_fullscreen) { - IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window); - } else if(!fullscreen && This->ddraw_fullscreen) { - IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window); + for(i=0; i < This->NumberOfSwapChains; i++) { + TRACE("Releasing the implicit swapchain %d\n", i); + if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) { + FIXME("(%p) Something's still holding the implicit swapchain\n", This); + } } - /* DirectDraw apps can change between fullscreen and windowed mode after device creation with - * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this. - * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag - * separately. - */ - This->ddraw_fullscreen = fullscreen; + HeapFree(GetProcessHeap(), 0, This->swapchains); + This->swapchains = NULL; + This->NumberOfSwapChains = 0; + return WINED3D_OK; } /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw @@ -2312,7 +2474,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, U devmode.dmSize = sizeof(devmode); devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; devmode.dmBitsPerPel = formatDesc->bpp * 8; - if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32; devmode.dmPelsWidth = pMode->Width; devmode.dmPelsHeight = pMode->Height; @@ -2347,10 +2508,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, U This->ddraw_height = pMode->Height; This->ddraw_format = pMode->Format; - /* Only do this with a window of course */ - if(This->ddraw_window) - MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE); - /* And finally clip mouse to our screen */ SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height); ClipCursor(&clip_rc); @@ -2416,6 +2573,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, if (StreamNumber >= MAX_STREAMS) { WARN("Stream out of range %d\n", StreamNumber); return WINED3DERR_INVALIDCALL; + } else if(OffsetInBytes & 0x3) { + WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes); + return WINED3DERR_INVALIDCALL; } oldSrc = This->updateStateBlock->streamSource[StreamNumber]; @@ -2444,8 +2604,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, return WINED3D_OK; } - /* Need to do a getParent and pass the reffs up */ - /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed. + /* Need to do a getParent and pass the references up */ + /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed. which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source so for now, just count internally */ if (pStreamData != NULL) { @@ -2492,6 +2652,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *ifa UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber]; UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber]; + /* Verify input at least in d3d9 this is invalid*/ + if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (Divider & WINED3DSTREAMSOURCE_INDEXEDDATA)){ + WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && StreamNumber == 0 ){ + WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + if( Divider == 0 ){ + WARN("Divider is 0, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider); This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA ); @@ -2530,7 +2704,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, W if (This->isRecordingState) { TRACE("Recording... not performing anything\n"); This->updateStateBlock->changed.transform[d3dts] = TRUE; - memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX)); + This->updateStateBlock->transforms[d3dts] = *lpmatrix; return WINED3D_OK; } @@ -2558,7 +2732,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, W */ /* Capture the times we can just ignore the change for now */ - if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */ + if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrix */ This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float)); /* Handled by the state manager */ } @@ -2570,7 +2744,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, W static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State)); - memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX)); + *pMatrix = This->stateBlock->transforms[State]; return WINED3D_OK; } @@ -2593,7 +2767,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface FIXME("Unhandled transform state!!\n"); } - multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix); + multiply_matrix(&temp, mat, pMatrix); /* Apply change via set transform - will reapply to eg. lights this way */ return IWineD3DDeviceImpl_SetTransform(iface, State, &temp); @@ -2677,7 +2851,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi); /* Save away the information */ - memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT)); + object->OriginalParms = *pLight; switch (pLight->Type) { case WINED3DLIGHT_POINT: @@ -2769,7 +2943,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD I return WINED3DERR_INVALIDCALL; } - memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT)); + *pLight = lightInfo->OriginalParms; return WINED3D_OK; } @@ -2824,7 +2998,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D } else { TRACE("Light already disabled, nothing to do\n"); } + lightInfo->enabled = FALSE; } else { + lightInfo->enabled = TRUE; if (lightInfo->glIndex != -1) { /* nop */ TRACE("Nothing to do as light was enabled\n"); @@ -2839,8 +3015,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D } } if(lightInfo->glIndex == -1) { - ERR("Too many concurrently active lights\n"); - return WINED3DERR_INVALIDCALL; + /* Our tests show that Windows returns D3D_OK in this situation, even with + * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This + * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE + * as well for those lights. + * + * TODO: Test how this affects rendering + */ + FIXME("Too many concurrently active lights\n"); + return WINED3D_OK; } /* i == lightInfo->glIndex */ @@ -2872,7 +3055,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, D return WINED3DERR_INVALIDCALL; } /* true is 128 according to SetLightEnable */ - *pEnable = lightInfo->glIndex != -1 ? 128 : 0; + *pEnable = lightInfo->enabled ? 128 : 0; return WINED3D_OK; } @@ -2965,7 +3148,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONS IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; This->updateStateBlock->changed.material = TRUE; - memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL)); + This->updateStateBlock->material = *pMaterial; /* Handle recording of state blocks */ if (This->isRecordingState) { @@ -2979,7 +3162,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONS static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL)); + *pMaterial = This->updateStateBlock->material; TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a); TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, @@ -3079,7 +3262,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONS TRACE("(%p)\n", This); This->updateStateBlock->changed.viewport = TRUE; - memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT)); + This->updateStateBlock->viewport = *pViewport; /* Handle recording of state blocks */ if (This->isRecordingState) { @@ -3098,7 +3281,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONS static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; TRACE("(%p)\n", This); - memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT)); + *pViewport = This->stateBlock->viewport; return WINED3D_OK; } @@ -3155,6 +3338,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); } + if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) { + ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler); + return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */ + } /** * SetSampler is designed to allow for more than the standard up to 8 textures * and Geforce has stopped supporting more than 6 standard textures in openGL. @@ -3200,6 +3387,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); } + if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) { + ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler); + return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */ + } *Value = This->stateBlock->samplerState[Sampler][Type]; TRACE("(%p) : Returning %#x\n", This, *Value); @@ -3229,7 +3420,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, C static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect)); + *pRect = This->updateStateBlock->scissorRect; TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom); return WINED3D_OK; } @@ -3442,6 +3633,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF( return WINED3D_OK; } +static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst( +IWineD3DDevice *iface, +UINT start, +CONST float *srcData, +UINT count) { + + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int i; + + TRACE("(iface %p, srcData %p, start %d, count %d)\n", + iface, srcData, start, count); + + /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ + if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF)) + return WINED3DERR_INVALIDCALL; + + memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); + if(TRACE_ON(d3d)) { + for (i = 0; i < count; i++) + TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, + srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + } + + /* 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 + */ + memset(This->activeContext->vshader_const_dirty + start, 1, + sizeof(*This->activeContext->vshader_const_dirty) * count); + This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count+1); + + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + + return WINED3D_OK; +} + static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF( IWineD3DDevice *iface, UINT start, @@ -3527,7 +3753,8 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) { device_update_fixed_function_usage_map(This); - if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) { + if (This->max_ffp_textures == This->max_ffp_texture_stages || + This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) { for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { if (!This->fixed_function_usage_map[i]) continue; @@ -3835,6 +4062,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF( return WINED3D_OK; } +static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst( + IWineD3DDevice *iface, + UINT start, + CONST float *srcData, + UINT count) { + + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int i; + + TRACE("(iface %p, srcData %p, start %d, count %d)\n", + iface, srcData, start, count); + + /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ + if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF)) + return WINED3DERR_INVALIDCALL; + + memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); + if(TRACE_ON(d3d)) { + for (i = 0; i < count; i++) + TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, + srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + } + + /* 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 + */ + memset(This->activeContext->pshader_const_dirty + start, 1, + sizeof(*This->activeContext->pshader_const_dirty) * count); + This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count+1); + + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); + + return WINED3D_OK; +} + static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF( IWineD3DDevice *iface, UINT start, @@ -3904,7 +4166,8 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo * write correct opengl data into it. It's cheap and allows us to run drawStridedFast */ if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { - CreateVBO(dest); + dest->Flags |= VBFLAG_CREATEVBO; + IWineD3DVertexBuffer_PreLoad((IWineD3DVertexBuffer *) dest); } if(dest->vbo) { @@ -4005,8 +4268,7 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo * against d3d8 or d3d9! */ - /* Clipping conditions: From - * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp + /* Clipping conditions: From msdn * * A vertex is clipped if it does not match the following requirements * -rhw < x <= rhw @@ -4220,12 +4482,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, ERR("Output vertex declaration not implemented yet\n"); } - /* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway, - * and this call is quite performance critical, so don't call needlessly - */ - if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } + /* Need any context to write to the vbo. */ + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP * control the streamIsUP flag, thus restore it afterwards. @@ -4237,7 +4495,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, if(vbo || SrcStartIndex) { unsigned int i; - /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcesVerticse are + /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure * * Also get the start index in, but only loop over all elements if there's something to add at all. @@ -4309,7 +4567,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if } if(Stage > This->stateBlock->lowest_disabled_stage && - StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) { + This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) { /* Colorop change above lowest disabled stage? That won't change anything in the gl setup * Changes in other states are important on disabled stages too */ @@ -4349,9 +4607,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if This->stateBlock->lowest_disabled_stage = i; TRACE("New lowest disabled: %d\n", i); } - if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) { - /* TODO: Built a stage -> texture unit mapping for register combiners */ - } } IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type)); @@ -4379,6 +4634,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); } + if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) { + ERR("Current stage overflows textures array (stage %d)\n", Stage); + return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */ + } + oldTexture = This->updateStateBlock->textures[Stage]; if(pTexture != NULL) { @@ -4471,6 +4731,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS); } + if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) { + ERR("Current stage overflows textures array (stage %d)\n", Stage); + return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */ + } + *ppTexture=This->stateBlock->textures[Stage]; if (*ppTexture) IWineD3DBaseTexture_AddRef(*ppTexture); @@ -4513,7 +4778,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, U HRESULT hr; if(iSwapChain > 0) { - hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain); + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain); if (hr == WINED3D_OK) { hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode); IWineD3DSwapChain_Release(swapChain); @@ -4538,31 +4803,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, U return hr; } -static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - TRACE("(%p)->(%p)\n", This, hWnd); - - if(This->ddraw_fullscreen) { - if(This->ddraw_window && This->ddraw_window != hWnd) { - IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window); - } - if(hWnd && This->ddraw_window != hWnd) { - IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd); - } - } - - This->ddraw_window = hWnd; - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - TRACE("(%p)->(%p)\n", This, hWnd); - - *hWnd = This->ddraw_window; - return WINED3D_OK; -} - /***** * Stateblock related functions *****/ @@ -4715,14 +4955,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { return WINED3DERR_INVALIDCALL; } - if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ - ENTER_GL(); glFlush(); - checkGLcall("glFlush"); - LEAVE_GL(); + /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever + * fails + */ This->inScene = FALSE; return WINED3D_OK; @@ -4740,7 +4978,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, for(i = 0 ; i < swapchains ; i ++) { - IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain); + IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain); TRACE("presentinng chain %d, %p\n", i, swapChain); IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0); IWineD3DSwapChain_Release(swapChain); @@ -4749,40 +4987,58 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, return WINED3D_OK; } -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]; - +/* 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) { GLbitfield glMask = 0; unsigned int i; - CONST WINED3DRECT* curRect; + WINED3DRECT curRect; + RECT vp_rect; + WINED3DVIEWPORT *vp = &This->stateBlock->viewport; + UINT drawable_width, drawable_height; + IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget; + IWineD3DSwapChainImpl *swapchain = NULL; - 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) { - 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; - } - - /* This is for offscreen rendering as well as for multithreading, thus activate the set render target - * and not the last active one. + /* 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 + * for the cleared parts, and the untouched parts. + * + * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten + * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set + * 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. */ - ActivateContext(This, This->render_targets[0], CTXUSAGE_CLEAR); + 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; + } + } + + target->get_drawable_size(target, &drawable_width, &drawable_height); + + ActivateContext(This, (IWineD3DSurface *) target, CTXUSAGE_CLEAR); ENTER_GL(); - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - apply_fbo_state(iface); - } - - if (Count > 0 && pRects) { - curRect = pRects; - } else { - curRect = NULL; - } - /* Only set the values up once, as they are not changing */ if (Flags & WINED3DCLEAR_STENCIL) { glClearStencil(Stencil); @@ -4792,11 +5048,29 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun } if (Flags & WINED3DCLEAR_ZBUFFER) { + DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; glDepthMask(GL_TRUE); 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, 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, 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, location); + } } if (Flags & WINED3DCLEAR_TARGET) { @@ -4812,59 +5086,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun glMask = glMask | GL_COLOR_BUFFER_BIT; } - if (!curRect) { - /* In drawable flag is set below */ - - if (This->render_offscreen) { - glScissor(This->stateBlock->viewport.X, - This->stateBlock->viewport.Y, - This->stateBlock->viewport.Width, - This->stateBlock->viewport.Height); + 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(This->render_offscreen) { + glScissor(vp_rect.left, vp_rect.top, + vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top); } else { - glScissor(This->stateBlock->viewport.X, - (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), - This->stateBlock->viewport.Width, - This->stateBlock->viewport.Height); + glScissor(vp_rect.left, drawable_height - vp_rect.bottom, + vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top); } checkGLcall("glScissor"); glClear(glMask); checkGLcall("glClear"); } else { - if(!(target->Flags & SFLAG_INDRAWABLE) && - !(wined3d_settings.offscreen_rendering_mode == ORM_FBO && This->render_offscreen && target->Flags & SFLAG_INTEXTURE)) { - - if(curRect[0].x1 > 0 || curRect[0].y1 > 0 || - curRect[0].x2 < target->currentDesc.Width || - curRect[0].y2 < target->currentDesc.Height) { - TRACE("Partial clear, and surface not in drawable. Blitting texture to drawable\n"); - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - } - } - /* Now process each rect in turn */ for (i = 0; i < Count; i++) { /* Note gl uses lower left, width/height */ - TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect, - curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2, - curRect[i].x1, (target->currentDesc.Height - curRect[i].y2), - curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1); + IntersectRect((RECT *) &curRect, &vp_rect, (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); /* 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[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) { + if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) { TRACE("Rectangle with negative dimensions, ignoring\n"); continue; } if(This->render_offscreen) { - glScissor(curRect[i].x1, curRect[i].y1, - curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1); + glScissor(curRect.x1, curRect.y1, + curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); } else { - glScissor(curRect[i].x1, target->currentDesc.Height - curRect[i].y2, - curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1); + glScissor(curRect.x1, drawable_height - curRect.y2, + curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); } checkGLcall("glScissor"); @@ -4883,21 +5150,48 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun 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(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE); + } + if (Flags & WINED3DCLEAR_ZBUFFER) { + /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */ + DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + surface_modify_ds_location(This->stencilBufferTarget, location); } LEAVE_GL(); - /* 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(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE); - /* TODO: Move the fbo logic into ModifyLocation() */ - if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - target->Flags |= SFLAG_INTEXTURE; + IWineD3DSurface_GetContainer( (IWineD3DSurface *) target, &IID_IWineD3DSwapChain, (void **)&swapchain); + if (swapchain) { + if (target == (IWineD3DSurfaceImpl*) swapchain->frontBuffer) { + glFlush(); + } + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } + return WINED3D_OK; } +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) { + 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); +} + /***** * Drawing functions *****/ @@ -4910,6 +5204,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WI debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount); + if(!This->stateBlock->vertexDecl) { + WARN("(%p) : Called without a valid vertex declaration set\n", This); + return WINED3DERR_INVALIDCALL; + } + /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */ if(This->stateBlock->streamIsUP) { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); @@ -4947,6 +5246,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice * return WINED3DERR_INVALIDCALL; } + if(!This->stateBlock->vertexDecl) { + WARN("(%p) : Called without a valid vertex declaration set\n", This); + return WINED3DERR_INVALIDCALL; + } + if(This->stateBlock->streamIsUP) { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); This->stateBlock->streamIsUP = FALSE; @@ -4985,6 +5289,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, debug_d3dprimitivetype(PrimitiveType), PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); + if(!This->stateBlock->vertexDecl) { + WARN("(%p) : Called without a valid vertex declaration set\n", This); + return WINED3DERR_INVALIDCALL; + } + /* Note in the following, it's not this type, but that's the purpose of streamIsUP */ vb = This->stateBlock->streamSource[0]; This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData; @@ -5025,6 +5334,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice * MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); + if(!This->stateBlock->vertexDecl) { + WARN("(%p) : Called without a valid vertex declaration set\n", This); + return WINED3DERR_INVALIDCALL; + } + if (IndexDataFormat == WINED3DFMT_INDEX16) { idxStride = 2; } else { @@ -5165,7 +5479,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, I /* check that both textures have the identical numbers of levels */ if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) { - WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture); + WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture); hr = WINED3DERR_INVALIDCALL; } @@ -5260,7 +5574,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, I static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) { IWineD3DSwapChain *swapChain; HRESULT hr; - hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain); + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain); if(hr == WINED3D_OK) { hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface); IWineD3DSwapChain_Release(swapChain); @@ -5270,27 +5584,103 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *if static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DBaseTextureImpl *texture; + const GlPixelFormatDesc *gl_info; + DWORD i; + + TRACE("(%p) : %p\n", This, pNumPasses); + + for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) { + if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) { + WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i); + return WINED3DERR_UNSUPPORTEDTEXTUREFILTER; + } + if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) { + WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i); + return WINED3DERR_UNSUPPORTEDTEXTUREFILTER; + } + + texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i]; + if(!texture) continue; + getFormatDescEntry(texture->resource.format, &GLINFO_LOCATION, &gl_info); + if(gl_info->Flags & WINED3DFMT_FLAG_FILTERING) continue; + + if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) { + WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i); + return E_FAIL; + } + if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) { + WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i); + return E_FAIL; + } + if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE && + This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) { + WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i); + return E_FAIL; + } + } + /* return a sensible default */ *pNumPasses = 1; - /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */ - FIXME("(%p) : stub\n", This); + + TRACE("returning D3D_OK\n"); return WINED3D_OK; } +static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device) +{ + int i; + + for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) { + IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i]; + if (texture && (texture->resource.format == WINED3DFMT_P8 || texture->resource.format == WINED3DFMT_A8P8)) { + IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i)); + } + } +} + static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; int j; + UINT NewSize; + PALETTEENTRY **palettes; + TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber); - if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) { - WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES); + + if (PaletteNumber >= MAX_PALETTES) { + ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES); return WINED3DERR_INVALIDCALL; } + + if (PaletteNumber >= This->NumberOfPalettes) { + NewSize = This->NumberOfPalettes; + do { + NewSize *= 2; + } while(PaletteNumber >= NewSize); + palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize); + if (!palettes) { + ERR("Out of memory!\n"); + return E_OUTOFMEMORY; + } + This->palettes = palettes; + This->NumberOfPalettes = NewSize; + } + + if (!This->palettes[PaletteNumber]) { + This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256); + if (!This->palettes[PaletteNumber]) { + ERR("Out of memory!\n"); + return E_OUTOFMEMORY; + } + } + for (j = 0; j < 256; ++j) { This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed; This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen; This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue; This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags; } + if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This); TRACE("(%p) : returning\n", This); return WINED3D_OK; } @@ -5299,8 +5689,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *ifa IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; int j; TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber); - if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) { - WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES); + if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) { + /* What happens in such situation isn't documented; Native seems to silently abort + on such conditions. Return Invalid Call. */ + ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes); return WINED3DERR_INVALIDCALL; } for (j = 0; j < 256; ++j) { @@ -5316,12 +5708,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *ifa static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber); - if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) { - WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES); + /* Native appears to silently abort on attempt to make an uninitialized palette current and render. + (tested with reference rasterizer). Return Invalid Call. */ + if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) { + ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes); return WINED3DERR_INVALIDCALL; } /*TODO: stateblocks */ - This->currentPalette = PaletteNumber; + if (This->currentPalette != PaletteNumber) { + This->currentPalette = PaletteNumber; + dirtify_p8_texture_samplers(This); + } TRACE("(%p) : returning\n", This); return WINED3D_OK; } @@ -5369,7 +5766,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus); - hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain); + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain); if(hr == WINED3D_OK){ hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus); IWineD3DSwapChain_Release(swapChain); @@ -5418,6 +5815,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */ glDescriptor *glDescription = NULL; GLenum dummy; + int sampler; int bpp; CONVERT_TYPES convert = NO_CONVERSION; @@ -5477,6 +5875,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, /* Make sure the surface is loaded and up to date */ IWineD3DSurface_PreLoad(pDestinationSurface); + IWineD3DSurface_BindTexture(pDestinationSurface); IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription); @@ -5524,7 +5923,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, /* not a whole row so we have to do it a line at a time */ int j; - /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */ + /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */ const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset; for(j = destTop ; j < (srcHeight + destTop) ; j++){ @@ -5588,7 +5987,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, LEAVE_GL(); IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0)); + sampler = This->rev_tex_unit_map[0]; + if (sampler != -1) { + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler)); + } return WINED3D_OK; } @@ -5645,7 +6047,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UI TRACE("Tesselation density or patch info changed, retesselating\n"); if(pRectPatchInfo) { - memcpy(&patch->RectPatchInfo, pRectPatchInfo, sizeof(*pRectPatchInfo)); + patch->RectPatchInfo = *pRectPatchInfo; } patch->numSegs[0] = pNumSegs[0]; patch->numSegs[1] = pNumSegs[1]; @@ -5676,7 +6078,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UI return WINED3D_OK; } -/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */ static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo); @@ -5704,7 +6105,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT } /* TODO: Write a test for the return value */ - FIXME("Attempt to destroy nonexistant patch\n"); + FIXME("Attempt to destroy nonexistent patch\n"); return WINED3DERR_INVALIDCALL; } @@ -5721,50 +6122,6 @@ static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) { return NULL; } -static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - if (!*fbo) { - GL_EXTCALL(glGenFramebuffersEXT(1, fbo)); - checkGLcall("glGenFramebuffersEXT()"); - } - GL_EXTCALL(glBindFramebufferEXT(target, *fbo)); - checkGLcall("glBindFramebuffer()"); -} - -static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) { - const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; - IWineD3DBaseTextureImpl *texture_impl; - GLenum texttarget, target; - GLint old_binding; - - texttarget = surface_impl->glDescription.target; - target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB; - glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding); - - IWineD3DSurface_PreLoad(surface); - - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(target, old_binding); - - /* Update base texture states array */ - if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) { - texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; - texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; - if (texture_impl->baseTexture.bindCount) { - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler)); - } - - IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl); - } - - GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, - surface_impl->glDescription.textureName, surface_impl->glDescription.level)); - - checkGLcall("attach_surface_fbo"); -} - static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DSwapChain *swapchain; @@ -5775,14 +6132,21 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS TRACE("Surface %p is onscreen\n", surface); + ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); buffer = surface_get_gl_buffer(surface, swapchain); glDrawBuffer(buffer); checkGLcall("glDrawBuffer()"); } else { TRACE("Surface %p is offscreen\n", surface); - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo); - attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface); + + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo); + context_attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT"); } if (rect) { @@ -5794,11 +6158,15 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS rect->x2 - rect->x1, rect->y2 - rect->y1); } checkGLcall("glScissor"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT); } 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)); @@ -5806,8 +6174,8 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS glClear(GL_COLOR_BUFFER_BIT); checkGLcall("glClear"); - if (This->render_offscreen) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); + if (This->activeContext->current_fbo) { + context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->current_fbo->id); } else { GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); checkGLcall("glBindFramebuffer()"); @@ -5818,6 +6186,8 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS glDrawBuffer(GL_BACK); checkGLcall("glDrawBuffer()"); } + + LEAVE_GL(); } static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) { @@ -5950,7 +6320,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD } } -/* rendertarget and deptth stencil functions */ +/* rendertarget and depth stencil functions */ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; @@ -6047,6 +6417,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain); } else { HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer); + Swapchain->backBuffer = NULL; } } @@ -6068,166 +6439,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice } } -/* TODO: Handle stencil attachments */ -static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil; - - TRACE("Set depth stencil to %p\n", depth_stencil); - - if (depth_stencil_impl) { - if (depth_stencil_impl->current_renderbuffer) { - GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id)); - checkGLcall("glFramebufferRenderbufferEXT()"); - } else { - IWineD3DBaseTextureImpl *texture_impl; - GLenum texttarget, target; - GLint old_binding = 0; - - texttarget = depth_stencil_impl->glDescription.target; - target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB; - glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding); - - IWineD3DSurface_PreLoad(depth_stencil); - - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); - glBindTexture(target, old_binding); - - /* Update base texture states array */ - if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) { - texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; - texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; - if (texture_impl->baseTexture.bindCount) { - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler)); - } - - IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl); - } - - GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, - depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level)); - checkGLcall("glFramebufferTexture2DEXT()"); - } - } else { - GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); - checkGLcall("glFramebufferTexture2DEXT()"); - } -} - -static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target; - - TRACE("Set render target %u to %p\n", idx, render_target); - - if (rtimpl) { - attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target); - This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx; - } else { - GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0)); - checkGLcall("glFramebufferTexture2DEXT()"); - - This->draw_buffers[idx] = GL_NONE; - } -} - -static void check_fbo_status(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - GLenum status; - - status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); - if (status == GL_FRAMEBUFFER_COMPLETE_EXT) { - TRACE("FBO complete\n"); - } else { - FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status); - - /* Dump the FBO attachments */ - if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) { - IWineD3DSurfaceImpl *attachment; - int i; - - for (i = 0; i < GL_LIMITS(buffers); ++i) { - attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i]; - if (attachment) { - FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format), - attachment->pow2Width, attachment->pow2Height); - } - } - attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment; - if (attachment) { - FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format), - attachment->pow2Width, attachment->pow2Height); - } - } - } -} - -static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0]; - IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget; - - if (!ds_impl) return FALSE; - - if (ds_impl->current_renderbuffer) { - return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width || - rt_impl->pow2Height != ds_impl->current_renderbuffer->height); - } - - return (rt_impl->pow2Width != ds_impl->pow2Width || - rt_impl->pow2Height != ds_impl->pow2Height); -} - -void apply_fbo_state(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - unsigned int i; - - if (This->render_offscreen) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); - - /* Apply render targets */ - for (i = 0; i < GL_LIMITS(buffers); ++i) { - IWineD3DSurface *render_target = This->render_targets[i]; - if (This->fbo_color_attachments[i] != render_target) { - set_render_target_fbo(iface, i, render_target); - This->fbo_color_attachments[i] = render_target; - } - } - - /* Apply depth targets */ - if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) { - unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width; - unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height; - - if (This->stencilBufferTarget) { - surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h); - } - set_depth_stencil_fbo(iface, This->stencilBufferTarget); - This->fbo_depth_attachment = This->stencilBufferTarget; - } - - if (GL_SUPPORT(ARB_DRAW_BUFFERS)) { - GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers)); - checkGLcall("glDrawBuffers()"); - } else { - glDrawBuffer(This->draw_buffers[0]); - checkGLcall("glDrawBuffer()"); - } - } else { - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - } - - check_fbo_status(iface); -} - void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect, IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */ IWineD3DSwapChain *src_swapchain, *dst_swapchain; GLenum gl_filter; + POINT offset = {0, 0}; 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); @@ -6250,45 +6468,74 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED /* Attach src surface to src fbo */ src_swapchain = get_swapchain(src_surface); if (src_swapchain) { - GLenum buffer; + GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain); TRACE("Source surface %p is onscreen\n", src_surface); ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD); + /* Make sure the drawable is up to date. In the offscreen case + * attach_surface_fbo() implicitly takes care of this. */ + IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL); + + 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; + } ENTER_GL(); GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0)); - buffer = surface_get_gl_buffer(src_surface, src_swapchain); glReadBuffer(buffer); checkGLcall("glReadBuffer()"); - - src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1; - src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2; } else { TRACE("Source surface %p is offscreen\n", src_surface); ENTER_GL(); - bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo); - attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface); + context_bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->activeContext->src_fbo); + context_attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); checkGLcall("glReadBuffer()"); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT"); } LEAVE_GL(); /* Attach dst surface to dst fbo */ dst_swapchain = get_swapchain(dst_surface); if (dst_swapchain) { - GLenum buffer; + GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain); TRACE("Destination surface %p is onscreen\n", dst_surface); ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD); + /* Make sure the drawable is up to date. In the offscreen case + * attach_surface_fbo() implicitly takes care of this. */ + IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL); + + 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; + } ENTER_GL(); GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)); - buffer = surface_get_gl_buffer(dst_surface, dst_swapchain); glDrawBuffer(buffer); checkGLcall("glDrawBuffer()"); - - dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1; - dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2; } else { TRACE("Destination surface %p is offscreen\n", dst_surface); @@ -6298,10 +6545,12 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED } ENTER_GL(); - bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo); - attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface); + context_bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo); + context_attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); checkGLcall("glDrawBuffer()"); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); + checkGLcall("glFramebufferRenderbufferEXT"); } glDisable(GL_SCISSOR_TEST); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); @@ -6316,8 +6565,10 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED checkGLcall("glBlitFramebuffer()"); } - if (This->render_offscreen) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); + IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE); + + if (This->activeContext->current_fbo) { + context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->current_fbo->id); } else { GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); checkGLcall("glBindFramebuffer()"); @@ -6339,22 +6590,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget); if (RenderTargetIndex >= GL_LIMITS(buffers)) { - ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers)); + WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n", + This, RenderTargetIndex, GL_LIMITS(buffers)); return WINED3DERR_INVALIDCALL; } /* MSDN says that null disables the render target but a device must always be associated with a render target nope MSDN says that we return invalid call to a null rendertarget with an index of 0 - - see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp - for more details */ if (RenderTargetIndex == 0 && pRenderTarget == NULL) { FIXME("Trying to set render target 0 to NULL\n"); return WINED3DERR_INVALIDCALL; } - if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) { + if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) { FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget); return WINED3DERR_INVALIDCALL; } @@ -6382,13 +6631,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets */ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT); - - /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the - * ctx properly. - * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be - * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called. - */ - ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); } return WINED3D_OK; } @@ -6403,16 +6645,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice * 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 incure an extra memory overhead + /** 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 incure an extra memory overhead + * stencil buffer and incur an extra memory overhead ******************************************************/ + if (This->stencilBufferTarget) { + ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); + surface_load_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); + surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); + } + tmp = This->stencilBufferTarget; This->stencilBufferTarget = pNewZStencil; - This->depth_copy_state = WINED3D_DCS_NO_COPY; /* should we be calling the parent or the wined3d surface? */ if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget); if (NULL != tmp) IWineD3DSurface_Release(tmp); @@ -6490,7 +6737,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i INT height = This->cursorHeight; INT width = This->cursorWidth; INT bpp = tableEntry->bpp; - INT i; + INT i, sampler; /* Reformat the texture memory (pitch and width can be * different) */ @@ -6510,7 +6757,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); checkGLcall("glActiveTextureARB"); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0)); + sampler = This->rev_tex_unit_map[0]; + if (sampler != -1) { + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler)); + } /* Create a new cursor texture */ glGenTextures(1, &This->cursorTexture); checkGLcall("glGenTextures"); @@ -6625,7 +6875,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* IWineD3DResourceImpl *resource; TRACE("(%p) : state (%u)\n", This, This->state); - /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */ + /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */ switch (This->state) { case WINED3D_OK: return WINED3D_OK; @@ -6672,7 +6922,8 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM } surface->currentDesc.Width = pPresentationParameters->BackBufferWidth; surface->currentDesc.Height = pPresentationParameters->BackBufferHeight; - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE) || + GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) { surface->pow2Width = pPresentationParameters->BackBufferWidth; surface->pow2Height = pPresentationParameters->BackBufferHeight; } else { @@ -6680,6 +6931,11 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM 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->glDescription.textureName) { ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -6694,8 +6950,137 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM } else { surface->Flags &= ~SFLAG_NONPOW2; } - HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory); + HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory); + surface->resource.allocatedMemory = NULL; + surface->resource.heapMemory = NULL; surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width; + /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */ + if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) { + IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE); + } else { + IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE); + } +} + +static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) { + TRACE("Unloading resource %p\n", resource); + IWineD3DResource_UnLoad(resource); + IWineD3DResource_Release(resource); + return S_OK; +} + +static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, WINED3DPRESENT_PARAMETERS *pp) { + UINT i, count; + WINED3DDISPLAYMODE m; + HRESULT hr; + + /* All Windowed modes are supported, as is leaving the current mode */ + if(pp->Windowed) return TRUE; + if(!pp->BackBufferWidth) return TRUE; + if(!pp->BackBufferHeight) return TRUE; + + count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN); + for(i = 0; i < count; i++) { + memset(&m, 0, sizeof(m)); + hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m); + if(FAILED(hr)) { + ERR("EnumAdapterModes failed\n"); + } + if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) { + /* Mode found, it is supported */ + return TRUE; + } + } + /* Mode not found -> not supported */ + return FALSE; +} + +void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface; + UINT i; + IWineD3DBaseShaderImpl *shader; + + IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL); + LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) { + This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader); + } + + ENTER_GL(); + if(This->depth_blt_texture) { + glDeleteTextures(1, &This->depth_blt_texture); + This->depth_blt_texture = 0; + } + if (This->depth_blt_rb) { + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb)); + This->depth_blt_rb = 0; + This->depth_blt_rb_w = 0; + This->depth_blt_rb_h = 0; + } + This->blitter->free_private(iface); + This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); + + for (i = 0; i < GL_LIMITS(textures); i++) { + /* Textures are recreated below */ + glDeleteTextures(1, &This->dummyTextureName[i]); + checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])"); + This->dummyTextureName[i] = 0; + } + LEAVE_GL(); + + while(This->numContexts) { + DestroyContext(This, This->contexts[0]); + } + This->activeContext = NULL; + HeapFree(GetProcessHeap(), 0, swapchain->context); + swapchain->context = NULL; + swapchain->num_contexts = 0; +} + +HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface; + HRESULT hr; + IWineD3DSurfaceImpl *target; + + /* Recreate the primary swapchain's context */ + swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); + if(swapchain->backBuffer) { + target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0]; + } else { + target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer; + } + swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE, + &swapchain->presentParms); + swapchain->num_contexts = 1; + This->activeContext = swapchain->context[0]; + + create_dummy_textures(This); + + hr = This->shader_backend->shader_alloc_private(iface); + if(FAILED(hr)) { + ERR("Failed to recreate shader private data\n"); + goto err_out; + } + hr = This->frag_pipe->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Fragment pipeline private data couldn't be allocated\n"); + goto err_out; + } + hr = This->blitter->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Blitter private data couldn't be allocated\n"); + goto err_out; + } + + return WINED3D_OK; + +err_out: + This->blitter->free_private(iface); + This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); + return hr; } static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) { @@ -6712,6 +7097,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE return hr; } + if(!is_display_mode_supported(This, pPresentationParameters)) { + WARN("Rejecting Reset() call because the requested display mode is not supported\n"); + WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth, + pPresentationParameters->BackBufferHeight); + return WINED3DERR_INVALIDCALL; + } + /* Is it necessary to recreate the gl context? Actually every setting can be changed * on an existing gl context, so there's no real need for recreation. * @@ -6753,10 +7145,19 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) { ERR("Cannot change the device window yet\n"); } - if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) { - ERR("What do do about a changed auto depth stencil parameter?\n"); + if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil_buffer) { + WARN("Auto depth stencil enabled, but no auto depth stencil present, returning WINED3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; } + /* Reset the depth stencil */ + if (pPresentationParameters->EnableAutoDepthStencil) + IWineD3DDevice_SetDepthStencilSurface(iface, This->auto_depth_stencil_buffer); + else + IWineD3DDevice_SetDepthStencilSurface(iface, NULL); + + delete_opengl_contexts(iface, (IWineD3DSwapChain *) swapchain); + if(pPresentationParameters->Windowed) { mode.Width = swapchain->orig_width; mode.Height = swapchain->orig_height; @@ -6794,6 +7195,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) { updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters); } + if(This->auto_depth_stencil_buffer) { + updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); + } + /* Now set the new viewport */ IWineD3DDevice_SetViewport(iface, &vp); @@ -6803,22 +7208,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) || DisplayModeChanged) { - /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */ - if(!pPresentationParameters->Windowed) { - IWineD3DDevice_SetFullscreen(iface, TRUE); - } - IWineD3DDevice_SetDisplayMode(iface, 0, &mode); - /* Switching out of fullscreen mode? First set the original res, then change the window */ - if(pPresentationParameters->Windowed) { - IWineD3DDevice_SetFullscreen(iface, FALSE); + if(swapchain->win_handle && !pPresentationParameters->Windowed) { + if(swapchain->presentParms.Windowed) { + /* switch from windowed to fs */ + IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle, + pPresentationParameters->BackBufferWidth, + pPresentationParameters->BackBufferHeight); + } else { + /* Fullscreen -> fullscreen mode change */ + MoveWindow(swapchain->win_handle, 0, 0, + pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, + TRUE); + } + } else if(swapchain->win_handle && !swapchain->presentParms.Windowed) { + /* Fullscreen -> windowed switch */ + IWineD3DDeviceImpl_RestoreWindow(iface, swapchain->win_handle); } swapchain->presentParms.Windowed = pPresentationParameters->Windowed; + } else if(!pPresentationParameters->Windowed) { + DWORD style = This->style, exStyle = This->exStyle; + /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into + * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call + * Reset to clear up their mess. Guild Wars also loses the device during that. + */ + This->style = 0; + This->exStyle = 0; + IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle, + pPresentationParameters->BackBufferWidth, + pPresentationParameters->BackBufferHeight); + This->style = style; + This->exStyle = exStyle; } + hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock); + if(FAILED(hr)) { + ERR("Resetting the stateblock failed with error 0x%08x\n", hr); + } + + hr = create_primary_opengl_context(iface, (IWineD3DSwapChain *) swapchain); IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); - return WINED3D_OK; + + /* All done. There is no need to reload resources or shaders, this will happen automatically on the + * first use + */ + return hr; } static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) { @@ -6841,11 +7276,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) { IWineD3DSwapChain *swapchain; - HRESULT hrc = WINED3D_OK; TRACE("Relaying to swapchain\n"); - if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) { + if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) { IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp); IWineD3DSwapChain_Release(swapchain); } @@ -6854,12 +7288,11 @@ static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) { IWineD3DSwapChain *swapchain; - HRESULT hrc = WINED3D_OK; TRACE("Relaying to swapchain\n"); - if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) { - hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp); + if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) { + IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp); IWineD3DSwapChain_Release(swapchain); } return; @@ -6871,7 +7304,7 @@ static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT i ** ********************************************************/ /** This function must be called in the release of a resource when ref == 0, * the contents of resource must still be correct, -* any handels to other resource held by the caller must be closed +* any handles to other resource held by the caller must be closed * (e.g. a texture should release all held surfaces because telling the device that it's been released.) *****************************************************/ static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){ @@ -6934,16 +7367,30 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW } for (i = 0; i < GL_LIMITS(buffers); ++i) { - if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); - set_render_target_fbo(iface, i, NULL); - This->fbo_color_attachments[i] = NULL; + if (This->render_targets[i] == (IWineD3DSurface *)resource) { + This->render_targets[i] = NULL; } } - if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); - set_depth_stencil_fbo(iface, NULL); - This->fbo_depth_attachment = NULL; + if (This->stencilBufferTarget == (IWineD3DSurface *)resource) { + This->stencilBufferTarget = NULL; + } + + for (i = 0; i < This->numContexts; ++i) { + struct fbo_entry *entry, *entry2; + int j; + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->contexts[i]->fbo_list, struct fbo_entry, entry) { + BOOL destroyed = FALSE; + for (j = 0; !destroyed && j < GL_LIMITS(buffers); ++j) { + if (entry->render_targets[j] == (IWineD3DSurface *)resource) { + context_destroy_fbo_entry(This, entry); + destroyed = TRUE; + } + } + if (!destroyed && entry->depth_stencil == (IWineD3DSurface *)resource) { + context_destroy_fbo_entry(This, entry); + } + } } } @@ -6991,12 +7438,6 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW This->stateBlock->streamSource[streamNumber] = 0; } } -#if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */ - else { /* This shouldn't happen */ - FIXME("Calling application has released the device before relasing all the resources bound to the device\n"); - } -#endif - } } break; @@ -7020,13 +7461,31 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW } - /* Remove the resoruce from the resourceStore */ + /* Remove the resource from the resourceStore */ IWineD3DDeviceImpl_RemoveResource(iface, resource); TRACE("Resource released\n"); } +static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DResourceImpl *resource, *cursor; + HRESULT ret; + TRACE("(%p)->(%p,%p)\n", This, pCallback, pData); + + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) { + TRACE("enumerating resource %p\n", resource); + IWineD3DResource_AddRef((IWineD3DResource *) resource); + ret = pCallback((IWineD3DResource *) resource, pData); + if(ret == S_FALSE) { + TRACE("Canceling enumeration\n"); + break; + } + } + return WINED3D_OK; +} + /********************************************************** * IWineD3DDevice VTbl follows **********************************************************/ @@ -7057,8 +7516,9 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_CreatePalette, /*** Odd functions **/ IWineD3DDeviceImpl_Init3D, + IWineD3DDeviceImpl_InitGDI, IWineD3DDeviceImpl_Uninit3D, - IWineD3DDeviceImpl_SetFullscreen, + IWineD3DDeviceImpl_UninitGDI, IWineD3DDeviceImpl_SetMultithreaded, IWineD3DDeviceImpl_EvictManagedResources, IWineD3DDeviceImpl_GetAvailableTextureMem, @@ -7068,8 +7528,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_GetDirect3D, IWineD3DDeviceImpl_GetDisplayMode, IWineD3DDeviceImpl_SetDisplayMode, - IWineD3DDeviceImpl_GetHWND, - IWineD3DDeviceImpl_SetHWND, IWineD3DDeviceImpl_GetNumberOfSwapChains, IWineD3DDeviceImpl_GetRasterStatus, IWineD3DDeviceImpl_GetSwapChain, @@ -7173,9 +7631,154 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_UpdateSurface, IWineD3DDeviceImpl_GetFrontBufferData, /*** object tracking ***/ - IWineD3DDeviceImpl_ResourceReleased + IWineD3DDeviceImpl_ResourceReleased, + IWineD3DDeviceImpl_EnumResources }; +const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl = +{ + /*** IUnknown methods ***/ + IWineD3DDeviceImpl_QueryInterface, + IWineD3DDeviceImpl_AddRef, + IWineD3DDeviceImpl_Release, + /*** IWineD3DDevice methods ***/ + IWineD3DDeviceImpl_GetParent, + /*** Creation methods**/ + IWineD3DDeviceImpl_CreateVertexBuffer, + IWineD3DDeviceImpl_CreateIndexBuffer, + IWineD3DDeviceImpl_CreateStateBlock, + IWineD3DDeviceImpl_CreateSurface, + IWineD3DDeviceImpl_CreateTexture, + IWineD3DDeviceImpl_CreateVolumeTexture, + IWineD3DDeviceImpl_CreateVolume, + IWineD3DDeviceImpl_CreateCubeTexture, + IWineD3DDeviceImpl_CreateQuery, + IWineD3DDeviceImpl_CreateAdditionalSwapChain, + IWineD3DDeviceImpl_CreateVertexDeclaration, + IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF, + IWineD3DDeviceImpl_CreateVertexShader, + IWineD3DDeviceImpl_CreatePixelShader, + IWineD3DDeviceImpl_CreatePalette, + /*** Odd functions **/ + IWineD3DDeviceImpl_Init3D, + IWineD3DDeviceImpl_InitGDI, + IWineD3DDeviceImpl_Uninit3D, + IWineD3DDeviceImpl_UninitGDI, + IWineD3DDeviceImpl_SetMultithreaded, + IWineD3DDeviceImpl_EvictManagedResources, + IWineD3DDeviceImpl_GetAvailableTextureMem, + IWineD3DDeviceImpl_GetBackBuffer, + IWineD3DDeviceImpl_GetCreationParameters, + IWineD3DDeviceImpl_GetDeviceCaps, + IWineD3DDeviceImpl_GetDirect3D, + IWineD3DDeviceImpl_GetDisplayMode, + IWineD3DDeviceImpl_SetDisplayMode, + IWineD3DDeviceImpl_GetNumberOfSwapChains, + IWineD3DDeviceImpl_GetRasterStatus, + IWineD3DDeviceImpl_GetSwapChain, + IWineD3DDeviceImpl_Reset, + IWineD3DDeviceImpl_SetDialogBoxMode, + IWineD3DDeviceImpl_SetCursorProperties, + IWineD3DDeviceImpl_SetCursorPosition, + IWineD3DDeviceImpl_ShowCursor, + IWineD3DDeviceImpl_TestCooperativeLevel, + /*** Getters and setters **/ + IWineD3DDeviceImpl_SetClipPlane, + IWineD3DDeviceImpl_GetClipPlane, + IWineD3DDeviceImpl_SetClipStatus, + IWineD3DDeviceImpl_GetClipStatus, + IWineD3DDeviceImpl_SetCurrentTexturePalette, + IWineD3DDeviceImpl_GetCurrentTexturePalette, + IWineD3DDeviceImpl_SetDepthStencilSurface, + IWineD3DDeviceImpl_GetDepthStencilSurface, + IWineD3DDeviceImpl_SetFVF, + IWineD3DDeviceImpl_GetFVF, + IWineD3DDeviceImpl_SetGammaRamp, + IWineD3DDeviceImpl_GetGammaRamp, + IWineD3DDeviceImpl_SetIndices, + IWineD3DDeviceImpl_GetIndices, + IWineD3DDeviceImpl_SetBaseVertexIndex, + IWineD3DDeviceImpl_GetBaseVertexIndex, + IWineD3DDeviceImpl_SetLight, + IWineD3DDeviceImpl_GetLight, + IWineD3DDeviceImpl_SetLightEnable, + IWineD3DDeviceImpl_GetLightEnable, + IWineD3DDeviceImpl_SetMaterial, + IWineD3DDeviceImpl_GetMaterial, + IWineD3DDeviceImpl_SetNPatchMode, + IWineD3DDeviceImpl_GetNPatchMode, + IWineD3DDeviceImpl_SetPaletteEntries, + IWineD3DDeviceImpl_GetPaletteEntries, + IWineD3DDeviceImpl_SetPixelShader, + IWineD3DDeviceImpl_GetPixelShader, + IWineD3DDeviceImpl_SetPixelShaderConstantB, + IWineD3DDeviceImpl_GetPixelShaderConstantB, + IWineD3DDeviceImpl_SetPixelShaderConstantI, + IWineD3DDeviceImpl_GetPixelShaderConstantI, + IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst, + IWineD3DDeviceImpl_GetPixelShaderConstantF, + IWineD3DDeviceImpl_SetRenderState, + IWineD3DDeviceImpl_GetRenderState, + IWineD3DDeviceImpl_SetRenderTarget, + IWineD3DDeviceImpl_GetRenderTarget, + IWineD3DDeviceImpl_SetFrontBackBuffers, + IWineD3DDeviceImpl_SetSamplerState, + IWineD3DDeviceImpl_GetSamplerState, + IWineD3DDeviceImpl_SetScissorRect, + IWineD3DDeviceImpl_GetScissorRect, + IWineD3DDeviceImpl_SetSoftwareVertexProcessing, + IWineD3DDeviceImpl_GetSoftwareVertexProcessing, + IWineD3DDeviceImpl_SetStreamSource, + IWineD3DDeviceImpl_GetStreamSource, + IWineD3DDeviceImpl_SetStreamSourceFreq, + IWineD3DDeviceImpl_GetStreamSourceFreq, + IWineD3DDeviceImpl_SetTexture, + IWineD3DDeviceImpl_GetTexture, + IWineD3DDeviceImpl_SetTextureStageState, + IWineD3DDeviceImpl_GetTextureStageState, + IWineD3DDeviceImpl_SetTransform, + IWineD3DDeviceImpl_GetTransform, + IWineD3DDeviceImpl_SetVertexDeclaration, + IWineD3DDeviceImpl_GetVertexDeclaration, + IWineD3DDeviceImpl_SetVertexShader, + IWineD3DDeviceImpl_GetVertexShader, + IWineD3DDeviceImpl_SetVertexShaderConstantB, + IWineD3DDeviceImpl_GetVertexShaderConstantB, + IWineD3DDeviceImpl_SetVertexShaderConstantI, + IWineD3DDeviceImpl_GetVertexShaderConstantI, + IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst, + IWineD3DDeviceImpl_GetVertexShaderConstantF, + IWineD3DDeviceImpl_SetViewport, + IWineD3DDeviceImpl_GetViewport, + IWineD3DDeviceImpl_MultiplyTransform, + IWineD3DDeviceImpl_ValidateDevice, + IWineD3DDeviceImpl_ProcessVertices, + /*** State block ***/ + IWineD3DDeviceImpl_BeginStateBlock, + IWineD3DDeviceImpl_EndStateBlock, + /*** Scene management ***/ + IWineD3DDeviceImpl_BeginScene, + IWineD3DDeviceImpl_EndScene, + IWineD3DDeviceImpl_Present, + IWineD3DDeviceImpl_Clear, + /*** Drawing ***/ + IWineD3DDeviceImpl_DrawPrimitive, + IWineD3DDeviceImpl_DrawIndexedPrimitive, + IWineD3DDeviceImpl_DrawPrimitiveUP, + IWineD3DDeviceImpl_DrawIndexedPrimitiveUP, + IWineD3DDeviceImpl_DrawPrimitiveStrided, + IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided, + IWineD3DDeviceImpl_DrawRectPatch, + IWineD3DDeviceImpl_DrawTriPatch, + IWineD3DDeviceImpl_DeletePatch, + IWineD3DDeviceImpl_ColorFill, + IWineD3DDeviceImpl_UpdateTexture, + IWineD3DDeviceImpl_UpdateSurface, + IWineD3DDeviceImpl_GetFrontBufferData, + /*** object tracking ***/ + IWineD3DDeviceImpl_ResourceReleased, + IWineD3DDeviceImpl_EnumResources +}; const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = { WINED3DRS_ALPHABLENDENABLE , @@ -7297,7 +7900,7 @@ const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = { }; void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { - DWORD rep = StateTable[state].representative; + DWORD rep = This->StateTable[state].representative; DWORD idx; BYTE shift; UINT i; @@ -7314,3 +7917,29 @@ void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { context->isStateDirty[idx] |= (1 << shift); } } + +void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { + IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice; + /* The drawable size of a pbuffer render target is the current pbuffer size + */ + *width = dev->pbufferWidth; + *height = dev->pbufferHeight; +} + +void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { + /* The drawable size of a fbo target is the opengl texture size, which is the power of two size + */ + *width = This->pow2Width; + *height = This->pow2Height; +} + +void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { + IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice; + /* 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 = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width; + *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height; +} diff --git a/reactos/dll/directx/wine/wined3d/directx.c b/reactos/dll/directx/wine/wined3d/directx.c index 493714d2d45..4e3249ed8fb 100644 --- a/reactos/dll/directx/wine/wined3d/directx.c +++ b/reactos/dll/directx/wine/wined3d/directx.c @@ -5,6 +5,7 @@ * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +29,6 @@ #define DEBUG_SINGLE_MODE 0 #endif - #include "config.h" #include #include "wined3d_private.h" @@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); +/* The d3d device ID */ +static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } }; + /* Extension detection */ static const struct { const char *extension_string; @@ -47,14 +50,18 @@ static const struct { {"GL_APPLE_fence", APPLE_FENCE, 0 }, {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 }, {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 }, + {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 }, /* ATI */ {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 }, {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 }, {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 }, {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 }, + {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 }, + {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 }, /* ARB */ + {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 }, {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 }, {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 }, {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 }, @@ -74,7 +81,8 @@ static const struct { {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 }, {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 }, {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 }, - {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 }, + {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) }, + {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 }, {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 }, {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 }, {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 }, @@ -82,7 +90,10 @@ static const struct { {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 }, /* EXT */ + {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 }, {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 }, + {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 }, + {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 }, {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 }, {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 }, {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 }, @@ -93,6 +104,7 @@ static const struct { {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 }, {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) }, {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 }, + {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 }, {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 }, {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 }, {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 }, @@ -101,7 +113,7 @@ static const struct { {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 }, {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 }, {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 }, - {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 }, + {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 }, /* NV */ {"GL_NV_half_float", NV_HALF_FLOAT, 0 }, @@ -122,6 +134,7 @@ static const struct { {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 }, {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 }, {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 }, + {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 }, /* SGI */ {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 }, @@ -135,18 +148,40 @@ static const struct { static int numAdapters = 0; static struct WineD3DAdapter Adapters[1]; +static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType); +static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType); +static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType); +static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType); + /* lookup tables */ int minLookup[MAX_LOOKUPS]; int maxLookup[MAX_LOOKUPS]; DWORD *stateLookup[MAX_LOOKUPS]; DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1]; +DWORD minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1] = { + {GL_NEAREST, GL_NEAREST, GL_NEAREST}, + {GL_NEAREST, GL_NEAREST, GL_NEAREST}, + {GL_NEAREST, GL_NEAREST, GL_NEAREST}, + {GL_NEAREST, GL_NEAREST, GL_NEAREST}, +}; +DWORD magLookup[WINED3DTEXF_ANISOTROPIC + 1]; +DWORD magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] = { + GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST +}; + +/* drawStridedSlow attributes */ +glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED]; +glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED]; +glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED]; +glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED]; +glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED]; /** - * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created - * ie there is no GL Context - Get a default rendering context to enable the - * function query some info from GL + * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created, + * i.e., there is no GL Context - Get a default rendering context to enable the + * function query some info from GL. */ static int wined3d_fake_gl_context_ref = 0; @@ -331,7 +366,7 @@ static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) { /* Set the shader type for this device, depending on the given capabilities, * the device type, and the user preferences in wined3d_settings */ -static void select_shader_mode( +void select_shader_mode( WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int* ps_selected, @@ -359,6 +394,8 @@ static void select_shader_mode( *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; } @@ -419,7 +456,8 @@ static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) { "!!ARBvp1.0\n" "PARAM C[66] = { program.env[0..65] };\n" "ADDRESS A0;" - "ARL A0.x, 0.0;\n" + "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n" + "ARL A0.x, zero.x;\n" "MOV result.position, C[A0.x + 65];\n" "END\n"; @@ -464,7 +502,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { GLfloat gl_floatv[2]; int major = 1, minor = 0; BOOL return_value = TRUE; - int i; + unsigned i; HDC hdc; unsigned int vidmem=0; @@ -485,8 +523,9 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->gl_vendor = VENDOR_NVIDIA; } else if (strstr(gl_string, "ATI")) { gl_info->gl_vendor = VENDOR_ATI; - } else if (strstr(gl_string, "Intel(R)") || - strstr(gl_info->gl_renderer, "Intel(R)")) { + } else if (strstr(gl_string, "Intel(R)") || + strstr(gl_info->gl_renderer, "Intel(R)") || + strstr(gl_string, "Intel Inc.")) { gl_info->gl_vendor = VENDOR_INTEL; } else if (strstr(gl_string, "Mesa")) { gl_info->gl_vendor = VENDOR_MESA; @@ -504,6 +543,25 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_string = (const char *) glGetString(GL_VERSION); if (gl_string != NULL) { + /* First, parse the generic opengl version. This is supposed not to be convoluted with + * driver specific information + */ + gl_string_cursor = gl_string; + major = atoi(gl_string_cursor); + if(major <= 0) { + ERR("Invalid opengl major version: %d\n", major); + } + while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') { + ++gl_string_cursor; + } + if (*gl_string_cursor++ != '.') { + ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string)); + } + minor = atoi(gl_string_cursor); + TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor); + gl_info->gl_version = MAKEDWORD_VERSION(major, minor); + + /* Now parse the driver specific string which we'll report to the app */ switch (gl_info->gl_vendor) { case VENDOR_NVIDIA: gl_string_cursor = strstr(gl_string, "NVIDIA"); @@ -573,7 +631,28 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } break; - case VENDOR_INTEL: + case VENDOR_INTEL: + /* Apple and Mesa version strings look differently, but both provide intel drivers */ + if(strstr(gl_string, "APPLE")) { + /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+ + * We only need the first part, and use the APPLE as identification + * "1.2 APPLE-1.4.56" + */ + gl_string_cursor = gl_string; + major = atoi(gl_string_cursor); + while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') { + ++gl_string_cursor; + } + + if (*gl_string_cursor++ != '.') { + ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string)); + break; + } + + minor = atoi(gl_string_cursor); + break; + } + case VENDOR_MESA: gl_string_cursor = strstr(gl_string, "Mesa"); gl_string_cursor = strstr(gl_string_cursor, " "); @@ -606,8 +685,14 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { major = 0; minor = 9; } - gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor); - TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version); + gl_info->driver_version = MAKEDWORD_VERSION(major, minor); + TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version); + /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */ + gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14); + } else { + FIXME("OpenGL driver did not return version information\n"); + gl_info->driver_version = MAKEDWORD_VERSION(0, 0); + gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14); } TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card); @@ -616,7 +701,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { * Initialize openGL extension related variables * with Default values */ - memset(&gl_info->supported, 0, sizeof(gl_info->supported)); + memset(gl_info->supported, 0, sizeof(gl_info->supported)); gl_info->max_buffers = 1; gl_info->max_textures = 1; gl_info->max_texture_stages = 1; @@ -655,10 +740,6 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->max_pointsize = gl_floatv[1]; TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]); - glGetIntegerv(GL_AUX_BUFFERS, &gl_max); - gl_info->max_aux_buffers = gl_max; - TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max); - /* Parse the gl supported features, in theory enabling parts of our code appropriately */ GL_Extensions = (const char *) glGetString(GL_EXTENSIONS); TRACE_(d3d_caps)("GL_Extensions reported:\n"); @@ -693,11 +774,14 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } } } + + LEAVE_GL(); + /* Now work out what GL support this card really has */ #define USE_GL_FUNC(type, pfn, ext, replace) { \ DWORD ver = ver_for_ext(ext); \ if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \ - else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \ + else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \ else gl_info->pfn = NULL; \ } GL_EXT_FUNCS_GEN; @@ -707,13 +791,14 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { WGL_EXT_FUNCS_GEN; #undef USE_GL_FUNC + ENTER_GL(); /* Now mark all the extensions supported which are included in the opengl core version. Do this *after* * loading the functions, otherwise the code above will load the extension entry points instead of the * core functions, which may not work */ for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) { if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE && - EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) { + EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) { TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string); gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; } @@ -727,6 +812,25 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { */ gl_info->supported[NV_FENCE] = FALSE; } + if (gl_info->supported[APPLE_FLOAT_PIXELS]) { + /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel + * + * The enums are the same: + * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A + * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B + * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814 + * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815 + * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B + */ + if(!gl_info->supported[ARB_TEXTURE_FLOAT]) { + TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n"); + gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE; + } + if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) { + TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n"); + gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE; + } + } if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) { TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n"); gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE; @@ -736,6 +840,13 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { * Won't occur in any real world situation though */ gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE; + if(gl_info->supported[NV_REGISTER_COMBINERS]) { + /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2 + * are supported. The nv extensions provide the same functionality as the + * ATI one, and a bit more(signed pixelformats) + */ + gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE; + } } if (gl_info->supported[ARB_DRAW_BUFFERS]) { glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max); @@ -785,14 +896,18 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { * a fixed function pipeline anymore. * * So this is just a check to check that our assumption holds true. If not, write a warning - * and reduce the number of vertex samplers or propably disable vertex texture fetch. + * and reduce the number of vertex samplers or probably disable vertex texture fetch. */ if(gl_info->max_vertex_samplers && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) { FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n", gl_info->max_vertex_samplers, gl_info->max_combined_samplers); FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n"); - gl_info->max_vertex_samplers = max(0, gl_info->max_combined_samplers - MAX_TEXTURES); + if( gl_info->max_combined_samplers > MAX_TEXTURES ) + gl_info->max_vertex_samplers = + gl_info->max_combined_samplers - MAX_TEXTURES; + else + gl_info->max_vertex_samplers = 0; } } else { gl_info->max_combined_samplers = gl_info->max_fragment_samplers; @@ -871,6 +986,30 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) { gl_info->ps_nv_version = PS_VERSION_20; } + if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) { + glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess); + } else { + gl_info->max_shininess = 128.0; + } + if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) { + /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it. + * This saves a few redundant glDisable calls + */ + gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE; + } + if(gl_info->supported[ATI_FRAGMENT_SHADER]) { + /* Disable NV_register_combiners and fragment shader if this is supported. + * generally the NV extensions are preferred over the ATI ones, and this + * extension is disabled if register_combiners and texture_shader2 are both + * supported. So we reach this place only if we have incomplete NV dxlevel 8 + * fragment processing support + */ + gl_info->supported[NV_REGISTER_COMBINERS] = FALSE; + gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER2] = FALSE; + gl_info->supported[NV_TEXTURE_SHADER3] = FALSE; + } } checkGLcall("extension detection\n"); @@ -931,7 +1070,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system * memory behind our backs if really needed. - * Note that the amout of video memory can be overruled using a registry setting. + * Note that the amount of video memory can be overruled using a registry setting. */ switch (gl_info->gl_vendor) { case VENDOR_NVIDIA: @@ -939,11 +1078,26 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. */ if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) { + /* Geforce9 - highend */ + if(strstr(gl_info->gl_renderer, "9800")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT; + vidmem = 512; + } + /* Geforce9 - midend */ + else if(strstr(gl_info->gl_renderer, "9600")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT; + vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */ + } /* Geforce8 - highend */ - if (strstr(gl_info->gl_renderer, "8800")) { + else if (strstr(gl_info->gl_renderer, "8800")) { gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS; vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */ } + /* Geforce8 - midend mobile */ + else if(strstr(gl_info->gl_renderer, "8600 M")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT; + vidmem = 512; + } /* Geforce8 - midend */ else if(strstr(gl_info->gl_renderer, "8600") || strstr(gl_info->gl_renderer, "8700")) @@ -969,10 +1123,23 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT; vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */ } - /* Geforce7 midend / Geforce6 highend */ - else if(strstr(gl_info->gl_renderer, "6800") || - strstr(gl_info->gl_renderer, "7600") || - strstr(gl_info->gl_renderer, "7700")) + /* Geforce7 midend */ + else if(strstr(gl_info->gl_renderer, "7600") || + strstr(gl_info->gl_renderer, "7700")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600; + vidmem = 256; /* The 7600 uses 256-512MB */ + /* Geforce7 lower medium */ + } else if(strstr(gl_info->gl_renderer, "7400")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400; + vidmem = 256; /* The 7400 uses 256-512MB */ + } + /* Geforce7 lowend */ + else if(strstr(gl_info->gl_renderer, "7300")) { + gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300; + vidmem = 256; /* Mac Pros with this card have 256 MB */ + } + /* Geforce6 highend */ + else if(strstr(gl_info->gl_renderer, "6800")) { gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800; vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */ @@ -1053,23 +1220,41 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { break; case VENDOR_ATI: if(WINE_D3D9_CAPABLE(gl_info)) { - /* Radeon R6xx HD2900 - highend */ - if (strstr(gl_info->gl_renderer, "HD 2900")) { + /* Radeon R6xx HD2900/HD3800 - highend */ + if (strstr(gl_info->gl_renderer, "HD 2900") || + strstr(gl_info->gl_renderer, "HD 3870") || + strstr(gl_info->gl_renderer, "HD 3850")) + { gl_info->gl_card = CARD_ATI_RADEON_HD2900; - vidmem = 512; /* HD2900 uses 512-1024MB */ + vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */ } - /* Radeon R6xx HD2600- midend */ - else if (strstr(gl_info->gl_renderer, "HD 2600")) { + /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */ + else if (strstr(gl_info->gl_renderer, "HD 2600") || + strstr(gl_info->gl_renderer, "HD 3830") || + strstr(gl_info->gl_renderer, "HD 3690") || + strstr(gl_info->gl_renderer, "HD 3650")) + { gl_info->gl_card = CARD_ATI_RADEON_HD2600; - vidmem = 256; /* HD2600 uses 256-512MB */ + vidmem = 256; /* HD2600/HD3600 uses 256-512MB */ } - /* Radeon R6xx HD2300/HD2400 - lowend */ + /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */ else if (strstr(gl_info->gl_renderer, "HD 2300") || - strstr(gl_info->gl_renderer, "HD 2400")) + strstr(gl_info->gl_renderer, "HD 2400") || + strstr(gl_info->gl_renderer, "HD 3470") || + strstr(gl_info->gl_renderer, "HD 3450") || + strstr(gl_info->gl_renderer, "HD 3430")) { gl_info->gl_card = CARD_ATI_RADEON_HD2300; vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ } + /* Radeon R6xx/R7xx integrated */ + else if (strstr(gl_info->gl_renderer, "HD 3100") || + strstr(gl_info->gl_renderer, "HD 3200") || + strstr(gl_info->gl_renderer, "HD 3300")) + { + gl_info->gl_card = CARD_ATI_RADEON_HD3200; + vidmem = 128; /* 128MB */ + } /* Radeon R5xx */ else if (strstr(gl_info->gl_renderer, "X1600") || strstr(gl_info->gl_renderer, "X1650") || @@ -1109,7 +1294,11 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } break; case VENDOR_INTEL: - if (strstr(gl_info->gl_renderer, "915GM")) { + if (strstr(gl_info->gl_renderer, "GMA 950")) { + /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */ + gl_info->gl_card = CARD_INTEL_I945GM; + vidmem = 64; + } else if (strstr(gl_info->gl_renderer, "915GM")) { gl_info->gl_card = CARD_INTEL_I915GM; } else if (strstr(gl_info->gl_renderer, "915G")) { gl_info->gl_card = CARD_INTEL_I915G; @@ -1142,7 +1331,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { else gl_info->gl_card = CARD_NVIDIA_RIVA_128; } - TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card); + TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card); /* If we have an estimate use it, else default to 64MB; */ if(vidmem) @@ -1155,10 +1344,6 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP; maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE; - minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE; - maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC; - - for (i = 0; i < MAX_LOOKUPS; i++) { stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) ); } @@ -1174,10 +1359,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] = gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT; - stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST; - stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST; - stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR; - stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] = + magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST; + magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST; + magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR; + magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST; @@ -1229,6 +1414,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->supported[WGL_ARB_PBUFFER] = TRUE; TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n"); } + if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) { + gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE; + TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n"); + } } } } @@ -1258,11 +1447,12 @@ static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) { IWineD3DImpl *This = (IWineD3DImpl *)iface; + TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter); + if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) { return NULL; } - TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter); return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY); } @@ -1387,23 +1577,8 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte if (DevModeW.dmFields & DM_DISPLAYFREQUENCY) pMode->RefreshRate = DevModeW.dmDisplayFrequency; - if (Format == WINED3DFMT_UNKNOWN) - { - switch (DevModeW.dmBitsPerPel) - { - case 8: - pMode->Format = WINED3DFMT_P8; - break; - case 16: - pMode->Format = WINED3DFMT_R5G6B5; - break; - case 32: - pMode->Format = WINED3DFMT_X8R8G8B8; - break; - default: - pMode->Format = WINED3DFMT_UNKNOWN; - ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel); - } + if (Format == WINED3DFMT_UNKNOWN) { + pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel); } else { pMode->Format = Format; } @@ -1456,14 +1631,7 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT A pMode->RefreshRate = DevModeW.dmDisplayFrequency; } - switch (bpp) { - case 8: pMode->Format = WINED3DFMT_R3G3B2; break; - case 16: pMode->Format = WINED3DFMT_R5G6B5; break; - case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */ - case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */ - default: pMode->Format = WINED3DFMT_UNKNOWN; - } - + pMode->Format = pixelformat_for_depth(bpp); } else { FIXME_(d3d_caps)("Adapter not primary display\n"); } @@ -1492,15 +1660,14 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad /* Note dx8 doesn't supply a DeviceName */ if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */ - /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */ - pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14); - pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version; + pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart; + pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version; *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor; *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card; *(pIdentifier->SubSysId) = 0; *(pIdentifier->Revision) = 0; + *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID; - /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */ if (Flags & WINED3DENUM_NO_WHQL_LEVEL) { *(pIdentifier->WHQLLevel) = 0; } else { @@ -1516,28 +1683,49 @@ static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_Pixe if(!cfg) return FALSE; - if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) { - ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format)); + if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */ + if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) { + ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format)); + return FALSE; + } + + if(cfg->redSize < redSize) + return FALSE; + + if(cfg->greenSize < greenSize) + return FALSE; + + if(cfg->blueSize < blueSize) + return FALSE; + + if(cfg->alphaSize < alphaSize) + return FALSE; + + return TRUE; + } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */ + if(Format == WINED3DFMT_R16F) + return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0); + if(Format == WINED3DFMT_G16R16F) + return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0); + if(Format == WINED3DFMT_A16B16G16R16F) + return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16); + if(Format == WINED3DFMT_R32F) + return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0); + if(Format == WINED3DFMT_G32R32F) + return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0); + if(Format == WINED3DFMT_A32B32G32R32F) + return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32); + } else { + /* Probably a color index mode */ return FALSE; } - if(cfg->redSize < redSize) - return FALSE; - - if(cfg->greenSize < greenSize) - return FALSE; - - if(cfg->blueSize < blueSize) - return FALSE; - - if(cfg->alphaSize < alphaSize) - return FALSE; - - return TRUE; + return FALSE; } static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) { short depthSize, stencilSize; + BOOL lockable = FALSE; if(!cfg) return FALSE; @@ -1547,9 +1735,17 @@ static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_Pixel return FALSE; } - if(cfg->depthSize < depthSize) + if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE)) + lockable = TRUE; + + /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports. + * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with + * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */ + if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize))) return FALSE; + /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so + * allow more stencil bits than requested. */ if(cfg->stencilSize < stencilSize) return FALSE; @@ -1597,7 +1793,10 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { IWineD3DImpl *This = (IWineD3DImpl *)iface; - TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n", + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *desc; + + TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n", This, Adapter, DeviceType, debug_d3ddevicetype(DeviceType), @@ -1610,33 +1809,86 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U return WINED3DERR_INVALIDCALL; } - /* TODO: Store in Adapter structure */ - if (pQualityLevels != NULL) { - static int s_single_shot = 0; - if (!s_single_shot) { - FIXME("Quality levels unsupported at present\n"); - s_single_shot = 1; - } - *pQualityLevels = 1; /* Guess at a value! */ - } + /* TODO: handle Windowed, add more quality levels */ if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK; + + /* By default multisampling is disabled right now as it causes issues + * on some Nvidia driver versions and it doesn't work well in combination + * with FBOs yet. */ + if(!wined3d_settings.allow_multisampling) + return WINED3DERR_NOTAVAILABLE; + + desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc); + if(!desc || !glDesc) { + return WINED3DERR_INVALIDCALL; + } + + if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) { + int i, nCfgs; + WineD3D_PixelFormat *cfgs; + + cfgs = Adapters[Adapter].cfgs; + nCfgs = Adapters[Adapter].nCfgs; + for(i=0; iFlags & WINED3DFMT_FLAG_RENDERTARGET) { + short redSize, greenSize, blueSize, alphaSize, colorBits; + int i, nCfgs; + WineD3D_PixelFormat *cfgs; + + if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) { + ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat); + return WINED3DERR_NOTAVAILABLE; + } + + cfgs = Adapters[Adapter].cfgs; + nCfgs = Adapters[Adapter].nCfgs; + for(i=0; i (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n", This, Adapter, - CheckType, debug_d3ddevicetype(CheckType), + DeviceType, debug_d3ddevicetype(DeviceType), DisplayFormat, debug_d3dformat(DisplayFormat), BackBufferFormat, debug_d3dformat(BackBufferFormat), Windowed); @@ -1646,29 +1898,607 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter return WINED3DERR_INVALIDCALL; } - cfgs = Adapters[Adapter].cfgs; - nCfgs = Adapters[Adapter].nCfgs; - for (it = 0; it < nCfgs; ++it) { - if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) { - hr = WINED3D_OK; - TRACE_(d3d_caps)("OK\n"); - break ; - } + /* The task of this function is to check whether a certain display / backbuffer format + * combination is available on the given adapter. In fullscreen mode microsoft specified + * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer + * and display format should match exactly. + * In windowed mode format conversion can occur and this depends on the driver. When format + * conversion is done, this function should nevertheless fail and applications need to use + * CheckDeviceFormatConversion. + * At the moment we assume that fullscreen and windowed have the same capabilities */ + + /* There are only 4 display formats */ + if(!((DisplayFormat == WINED3DFMT_R5G6B5) || + (DisplayFormat == WINED3DFMT_X1R5G5B5) || + (DisplayFormat == WINED3DFMT_X8R8G8B8) || + (DisplayFormat == WINED3DFMT_A2R10G10B10))) + { + TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat)); + return WINED3DERR_NOTAVAILABLE; } - if(hr != WINED3D_OK) - ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat)); + /* If the requested DisplayFormat is not available, don't continue */ + nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat); + if(!nmodes) { + TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat)); + return WINED3DERR_NOTAVAILABLE; + } - if(hr != WINED3D_OK) - TRACE_(d3d_caps)("returning something different from WINED3D_OK\n"); + /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */ + if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) { + TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n"); + return WINED3DERR_NOTAVAILABLE; + } + + /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */ + if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) { + TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat)); + return WINED3DERR_NOTAVAILABLE; + } + + /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */ + if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) { + TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat)); + return WINED3DERR_NOTAVAILABLE; + } + + /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */ + if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) { + TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat)); + return WINED3DERR_NOTAVAILABLE; + } + + /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */ + if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) { + TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat)); + return WINED3DERR_NOTAVAILABLE; + } + + /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */ + hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL); + if(FAILED(hr)) + TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat)); return hr; } + #define GLINFO_LOCATION Adapters[Adapter].gl_info +/* Check if we support bumpmapping for a format */ +static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat) +{ + const struct fragment_pipeline *fp; + const GlPixelFormatDesc *glDesc; + + switch(CheckFormat) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_Q8W8V8U8: + getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc); + if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) { + /* We have a GL extension giving native support */ + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + + /* No native support: Ask the fixed function pipeline implementation if it + * can deal with the conversion + */ + fp = select_fragment_implementation(Adapter, DeviceType); + if(fp->conv_supported(CheckFormat)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } else { + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + + default: + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } +} + +/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */ +static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat) +{ + int it=0; + WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs; + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc); + + /* Fail if we weren't able to get a description of the format */ + if(!desc || !glDesc) + return FALSE; + + /* Only allow depth/stencil formats */ + if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) + return FALSE; + + /* Walk through all WGL pixel formats to find a match */ + cfgs = Adapters[Adapter].cfgs; + for (it = 0; it < Adapters[Adapter].nCfgs; ++it) { + if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) { + if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) { + return TRUE; + } + } + } + + return FALSE; +} + +static BOOL CheckFilterCapability(UINT Adapter, WINED3DFORMAT CheckFormat) +{ + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc); + + /* Fail if we weren't able to get a description of the format */ + if(!desc || !glDesc) + return FALSE; + + /* The flags entry of a format contains the filtering capability */ + if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) + return TRUE; + + return FALSE; +} + +/* Check the render target capabilities of a format */ +static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat) +{ + UINT Adapter = 0; + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc); + + /* Fail if we weren't able to get a description of the format */ + if(!desc || !glDesc) + return FALSE; + + /* Filter out non-RT formats */ + if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) + return FALSE; + + if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) { + WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs; + int it; + short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize; + short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize; + + getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize); + getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize); + + /* In backbuffer mode the front and backbuffer share the same WGL pixelformat. + * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */ + if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) { + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + + /* Check if there is a WGL pixel format matching the requirements, the format should also be window + * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */ + for (it = 0; it < Adapters[Adapter].nCfgs; ++it) { + if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) { + TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat)); + 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 = Adapters[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 < Adapters[Adapter].nCfgs; ++it) { + if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) { + TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat)); + return TRUE; + } + } + } 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; + } + return FALSE; +} + +static BOOL CheckSrgbReadCapability(UINT Adapter, WINED3DFORMAT CheckFormat) +{ + /* Check for supported sRGB formats (Texture loading and framebuffer) */ + if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) { + TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n"); + return FALSE; + } + + switch (CheckFormat) { + case WINED3DFMT_A8R8G8B8: + case WINED3DFMT_X8R8G8B8: + case WINED3DFMT_A4R4G4B4: + case WINED3DFMT_L8: + case WINED3DFMT_A8L8: + 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(CheckFormat)); + return FALSE; + } + return FALSE; +} + +static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat) +{ + /* 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((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) { + int vs_selected_mode; + int ps_selected_mode; + select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); + + if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + } + + TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat)); + return FALSE; +} + +/* Check if a format support blending in combination with pixel shaders */ +static BOOL CheckPostPixelShaderBlendingCapability(UINT Adapter, WINED3DFORMAT CheckFormat) +{ + const GlPixelFormatDesc *glDesc; + const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc); + + /* Fail if we weren't able to get a description of the format */ + if(!desc || !glDesc) + return FALSE; + + /* The flags entry of a format contains the post pixel shader blending capability */ + if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) + return TRUE; + + return FALSE; +} + +static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) { + /* 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 + * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show + * that wrapping is supported. The lack of filtering will sort out the mipmapping + * capability anyway. + * + * For now lets report this on all formats, but in the future we may want to + * restrict it to some should games need that + */ + return TRUE; +} + +/* Check if a texture format is supported on the given adapter */ +static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat) +{ + const shader_backend_t *shader_backend; + const struct fragment_pipeline *fp; + const GlPixelFormatDesc *glDesc; + + switch (CheckFormat) { + + /***** + * supported: RGB(A) formats + */ + case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */ + case WINED3DFMT_A8R8G8B8: + case WINED3DFMT_X8R8G8B8: + case WINED3DFMT_R5G6B5: + case WINED3DFMT_X1R5G5B5: + case WINED3DFMT_A1R5G5B5: + case WINED3DFMT_A4R4G4B4: + case WINED3DFMT_A8: + case WINED3DFMT_X4R4G4B4: + case WINED3DFMT_A8B8G8R8: + case WINED3DFMT_X8B8G8R8: + case WINED3DFMT_A2R10G10B10: + case WINED3DFMT_A2B10G10R10: + case WINED3DFMT_G16R16: + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + + case WINED3DFMT_R3G3B2: + TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n"); + return FALSE; + + /***** + * supported: Palettized + */ + case WINED3DFMT_P8: + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + /* No Windows driver offers A8P8, so don't offer it either */ + case WINED3DFMT_A8P8: + return FALSE; + + /***** + * Supported: (Alpha)-Luminance + */ + case WINED3DFMT_L8: + case WINED3DFMT_A8L8: + case WINED3DFMT_L16: + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + + /* Not supported on Windows, thus disabled */ + case WINED3DFMT_A4L4: + TRACE_(d3d_caps)("[FAILED] - not supported on windows\n"); + return FALSE; + + /***** + * Supported: Depth/Stencil formats + */ + case WINED3DFMT_D16_LOCKABLE: + case WINED3DFMT_D16: + case WINED3DFMT_D15S1: + case WINED3DFMT_D24X8: + case WINED3DFMT_D24X4S4: + case WINED3DFMT_D24S8: + case WINED3DFMT_D24FS8: + case WINED3DFMT_D32: + case WINED3DFMT_D32F_LOCKABLE: + return TRUE; + + /***** + * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or + * GL_NV_texture_shader). Emulated by shaders + */ + case WINED3DFMT_V8U8: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_Q8W8V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_W11V11U10: + getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc); + if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) { + /* We have a GL extension giving native support */ + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + + /* No native support: Ask the fixed function pipeline implementation if it + * can deal with the conversion + */ + shader_backend = select_shader_backend(Adapter, DeviceType); + if(shader_backend->shader_conv_supported(CheckFormat)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } else { + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + + case WINED3DFMT_DXT1: + case WINED3DFMT_DXT2: + case WINED3DFMT_DXT3: + case WINED3DFMT_DXT4: + case WINED3DFMT_DXT5: + if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + + /***** + * Odd formats - not supported + */ + case WINED3DFMT_VERTEXDATA: + case WINED3DFMT_INDEX16: + case WINED3DFMT_INDEX32: + case WINED3DFMT_Q16W16V16U16: + case WINED3DFMT_A2W10V10U10: + TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ + return FALSE; + + /***** + * WINED3DFMT_CxV8U8: Not supported right now + */ + case WINED3DFMT_CxV8U8: + TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ + return FALSE; + + /* YUV formats */ + case WINED3DFMT_UYVY: + case WINED3DFMT_YUY2: + if(GL_SUPPORT(APPLE_YCBCR_422)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + case WINED3DFMT_YV12: + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + /* Not supported */ + case WINED3DFMT_A16B16G16R16: + case WINED3DFMT_A8R3G3B2: + TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ + return FALSE; + + /* Floating point formats */ + case WINED3DFMT_R16F: + case WINED3DFMT_A16B16G16R16F: + if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + case WINED3DFMT_R32F: + case WINED3DFMT_A32B32G32R32F: + if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + case WINED3DFMT_G16R16F: + case WINED3DFMT_G32R32F: + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support + * instancing. To query if the card supports instancing CheckDeviceFormat with the special format + * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value. + * We can do instancing with all shader versions, but we need vertex shaders. + * + * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once + * to enable instancing. WineD3D doesn't need that and just ignores it. + * + * With Shader Model 3.0 capable cards Instancing 'just works' in Windows. + */ + case WINEMAKEFOURCC('I','N','S','T'): + TRACE("ATI Instancing check hack\n"); + if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + /* Some weird FOURCC formats */ + case WINED3DFMT_R8G8_B8G8: + case WINED3DFMT_G8R8_G8B8: + case WINED3DFMT_MULTI2_ARGB8: + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + /* Vendor specific formats */ + case WINED3DFMT_ATI2N: + if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { + shader_backend = select_shader_backend(Adapter, DeviceType); + fp = select_fragment_implementation(Adapter, DeviceType); + if(shader_backend->shader_conv_supported(CheckFormat) && + fp->conv_supported(CheckFormat)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + case WINED3DFMT_NVHU: + case WINED3DFMT_NVHS: + /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU + * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes + * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16). + * ATI refused to support formats which can easilly be emulated with pixel shaders, so + * Applications have to deal with not having NVHS and NVHU. + */ + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + + case WINED3DFMT_UNKNOWN: + return FALSE; + + default: + ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat)); + break; + } + return FALSE; +} + +static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) { + const struct blit_shader *blitter; + + if(SurfaceType == SURFACE_GDI) { + switch(CheckFormat) { + case WINED3DFMT_R8G8B8: + case WINED3DFMT_A8R8G8B8: + case WINED3DFMT_X8R8G8B8: + case WINED3DFMT_R5G6B5: + case WINED3DFMT_X1R5G5B5: + case WINED3DFMT_A1R5G5B5: + case WINED3DFMT_A4R4G4B4: + case WINED3DFMT_R3G3B2: + case WINED3DFMT_A8: + case WINED3DFMT_A8R3G3B2: + case WINED3DFMT_X4R4G4B4: + case WINED3DFMT_A2B10G10R10: + case WINED3DFMT_A8B8G8R8: + case WINED3DFMT_X8B8G8R8: + case WINED3DFMT_G16R16: + case WINED3DFMT_A2R10G10B10: + case WINED3DFMT_A16B16G16R16: + case WINED3DFMT_P8: + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + default: + TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n"); + return FALSE; + } + } + + /* All format that are supported for textures are supported for surfaces as well */ + if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE; + /* All depth stencil formats are supported on surfaces */ + if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) return TRUE; + + /* If opengl can't process the format natively, the blitter may be able to convert it */ + blitter = select_blit_implementation(Adapter, DeviceType); + if(blitter->conv_supported(CheckFormat)) { + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + } + + /* Reject other formats */ + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; +} + +static BOOL CheckVertexTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat) +{ + if (!GL_LIMITS(vertex_samplers)) { + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + + switch (CheckFormat) { + case WINED3DFMT_A32B32G32R32F: + if (!GL_SUPPORT(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; +} + static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, - WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) { + WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, + WINED3DSURFTYPE SurfaceType) { IWineD3DImpl *This = (IWineD3DImpl *)iface; + 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", This, Adapter, @@ -1682,30 +2512,383 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_INVALIDCALL; } - if (Usage & WINED3DUSAGE_QUERY_FILTER) { - switch (CheckFormat) { - /* Filtering not supported */ - case WINED3DFMT_R32F: - case WINED3DFMT_A32B32G32R32F: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - default: - break; - } - } + if(RType == WINED3DRTYPE_CUBETEXTURE) { - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { - TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n"); + if(SurfaceType != SURFACE_OPENGL) { + TRACE("[FAILED]\n"); return WINED3DERR_NOTAVAILABLE; } - } - if(RType == WINED3DRTYPE_VOLUMETEXTURE) { - if(!GL_SUPPORT(EXT_TEXTURE3D)) { + /* Cubetexture allows: + * - D3DUSAGE_AUTOGENMIPMAP + * - D3DUSAGE_DEPTHSTENCIL + * - D3DUSAGE_DYNAMIC + * - D3DUSAGE_NONSECURE (d3d9ex) + * - D3DUSAGE_RENDERTARGET + * - D3DUSAGE_SOFTWAREPROCESSING + * - D3DUSAGE_QUERY_WRAPANDMIP + */ + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + /* Check if the texture format is around */ + if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) { + if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + /* Check for automatic mipmap generation support */ + if(GL_SUPPORT(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"); + } + } + + /* Always report dynamic locking */ + if(Usage & WINED3DUSAGE_DYNAMIC) + UsageCaps |= WINED3DUSAGE_DYNAMIC; + + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Always report software processing */ + if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; + + /* Check QUERY_FILTER support */ + if(Usage & WINED3DUSAGE_QUERY_FILTER) { + if(CheckFilterCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; + } else { + TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_POSTPIXELSHADER_BLENDING support */ + if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { + if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; + } else { + TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBREAD support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { + if(CheckSrgbReadCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBWRITE support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { + if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_VERTEXTEXTURE support */ + if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { + if(CheckVertexTextureCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_WRAPANDMIP support */ + if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { + if(CheckWrapAndMipCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; + } else { + TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + } else { + TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\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, AdapterFormat, DeviceType, CheckFormat, SurfaceType)) { + if(Usage & WINED3DUSAGE_DEPTHSTENCIL) { + if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; + } else { + TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_POSTPIXELSHADER_BLENDING support */ + if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { + if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; + } else { + TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + } else { + TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n"); + return WINED3DERR_NOTAVAILABLE; + } + + } 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 + */ + + if(SurfaceType != SURFACE_OPENGL) { + TRACE("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } + + /* Check if the texture format is around */ + if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) { + if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + /* Check for automatic mipmap generation support */ + if(GL_SUPPORT(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"); + } + } + + /* Always report dynamic locking */ + if(Usage & WINED3DUSAGE_DYNAMIC) + UsageCaps |= WINED3DUSAGE_DYNAMIC; + + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Always report software processing */ + if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; + + /* Check QUERY_FILTER support */ + if(Usage & WINED3DUSAGE_QUERY_FILTER) { + if(CheckFilterCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; + } else { + TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_LEGACYBUMPMAP support */ + if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) { + if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP; + } else { + TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_POSTPIXELSHADER_BLENDING support */ + if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { + if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; + } else { + TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBREAD support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { + if(CheckSrgbReadCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBWRITE support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { + if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_VERTEXTEXTURE support */ + if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { + if(CheckVertexTextureCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_WRAPANDMIP support */ + if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { + if(CheckWrapAndMipCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP; + } else { + TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + if(Usage & WINED3DUSAGE_DEPTHSTENCIL) { + if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; + } else { + TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + } 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 + */ + + if(SurfaceType != SURFACE_OPENGL) { + TRACE("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } + + /* Check volume texture and volume usage caps */ + if(GL_SUPPORT(EXT_TEXTURE3D)) { + if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) { + TRACE_(d3d_caps)("[FAILED] - Format not supported\n"); + return WINED3DERR_NOTAVAILABLE; + } + + /* Always report dynamic locking */ + if(Usage & WINED3DUSAGE_DYNAMIC) + UsageCaps |= WINED3DUSAGE_DYNAMIC; + + /* Always report software processing */ + if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING) + UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING; + + /* Check QUERY_FILTER support */ + if(Usage & WINED3DUSAGE_QUERY_FILTER) { + if(CheckFilterCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_FILTER; + } else { + TRACE_(d3d_caps)("[FAILED] - No query filter support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_POSTPIXELSHADER_BLENDING support */ + if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) { + if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; + } else { + TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBREAD support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) { + if(CheckSrgbReadCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_SRGBWRITE support */ + if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) { + if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_VERTEXTEXTURE support */ + if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { + if(CheckVertexTextureCapability(Adapter, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE; + } else { + TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + + /* Check QUERY_WRAPANDMIP support */ + if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) { + if(CheckWrapAndMipCapability(Adapter, CheckFormat)) { + 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 @@ -1719,6 +2902,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt case WINED3DFMT_R16F: case WINED3DFMT_X8L8V8U8: case WINED3DFMT_L6V5U5: + case WINED3DFMT_G16R16: TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n"); return WINED3DERR_NOTAVAILABLE; @@ -1754,167 +2938,12 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt /* Do nothing, continue with checking the format below */ break; } - } - /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants - * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp - * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */ - if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) { - if (!GL_LIMITS(vertex_samplers)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - - switch (CheckFormat) { - case WINED3DFMT_A32B32G32R32F: - if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } - - if(Usage & WINED3DUSAGE_DEPTHSTENCIL) { - switch (CheckFormat) { - /* In theory we could do all formats, just fetch them accordingly should the buffer be locked. - * Windows supports only those 3, and enumerating the other formats confuses applications - */ - case WINED3DFMT_D24S8: - case WINED3DFMT_D24X8: - case WINED3DFMT_D16: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - case WINED3DFMT_D16_LOCKABLE: - case WINED3DFMT_D24FS8: - case WINED3DFMT_D32F_LOCKABLE: - case WINED3DFMT_D24X4S4: - case WINED3DFMT_D15S1: - case WINED3DFMT_D32: - TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n"); - return WINED3DERR_NOTAVAILABLE; - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } else if(Usage & WINED3DUSAGE_RENDERTARGET) { - switch (CheckFormat) { - case WINED3DFMT_R8G8B8: - case WINED3DFMT_A8R8G8B8: - case WINED3DFMT_X8R8G8B8: - case WINED3DFMT_R5G6B5: - case WINED3DFMT_X1R5G5B5: - case WINED3DFMT_A1R5G5B5: - case WINED3DFMT_A4R4G4B4: - case WINED3DFMT_R3G3B2: - case WINED3DFMT_X4R4G4B4: - case WINED3DFMT_A8B8G8R8: - case WINED3DFMT_X8B8G8R8: - case WINED3DFMT_P8: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - case WINED3DFMT_R16F: - case WINED3DFMT_A16B16G16R16F: - if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - case WINED3DFMT_A32B32G32R32F: - if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) { - if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) { - switch (CheckFormat) { - case WINED3DFMT_V8U8: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - /* TODO: Other bump map formats */ - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } - if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { - switch (CheckFormat) { - case WINED3DFMT_V8U8: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } - TRACE_(d3d_caps)("[FAILED]\n"); + } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){ + /* 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; } - if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { - switch (CheckFormat) { - case WINED3DFMT_DXT1: - case WINED3DFMT_DXT2: - case WINED3DFMT_DXT3: - case WINED3DFMT_DXT4: - case WINED3DFMT_DXT5: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - break; /* Avoid compiler warnings */ - } - } - - /* Check for supported sRGB formats (Texture loading and framebuffer) */ - if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) { - switch (CheckFormat) { - case WINED3DFMT_A8R8G8B8: - case WINED3DFMT_X8R8G8B8: - case WINED3DFMT_A4R4G4B4: - case WINED3DFMT_L8: - case WINED3DFMT_A8L8: - case WINED3DFMT_DXT1: - case WINED3DFMT_DXT2: - case WINED3DFMT_DXT3: - case WINED3DFMT_DXT4: - case WINED3DFMT_DXT5: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - - default: - TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat)); - return WINED3DERR_NOTAVAILABLE; - } - } - - if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - - BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL); - - switch (CheckFormat) { - case WINED3DFMT_R16F: - case WINED3DFMT_A16B16G16R16F: - if (!half_pixel_support) break; - case WINED3DFMT_R32F: - case WINED3DFMT_A32B32G32R32F: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - break; /* Avoid compiler warnings */ - } - } - /* This format is nothing special and it is supported perfectly. * However, ati and nvidia driver on windows do not mark this format as * supported (tested with the dxCapsViewer) and pretending to @@ -1927,129 +2956,17 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_NOTAVAILABLE; } - switch (CheckFormat) { - - /***** - * supported: RGB(A) formats - */ - case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */ - case WINED3DFMT_A8R8G8B8: - case WINED3DFMT_X8R8G8B8: - case WINED3DFMT_R5G6B5: - case WINED3DFMT_X1R5G5B5: - case WINED3DFMT_A1R5G5B5: - case WINED3DFMT_A4R4G4B4: - case WINED3DFMT_R3G3B2: - case WINED3DFMT_A8: - case WINED3DFMT_X4R4G4B4: - case WINED3DFMT_A8B8G8R8: - case WINED3DFMT_X8B8G8R8: - case WINED3DFMT_A2R10G10B10: - case WINED3DFMT_A2B10G10R10: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - - /***** - * supported: Palettized - */ - case WINED3DFMT_P8: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - - /***** - * Supported: (Alpha)-Luminance - */ - case WINED3DFMT_L8: - case WINED3DFMT_A8L8: - case WINED3DFMT_A4L4: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - - /***** - * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or - * GL_NV_texture_shader), but advertized to make apps happy. - * Enable some because games often fail when they are not available - * and are still playable even without bump mapping - */ - case WINED3DFMT_V8U8: - case WINED3DFMT_V16U16: - case WINED3DFMT_L6V5U5: - case WINED3DFMT_X8L8V8U8: - case WINED3DFMT_Q8W8V8U8: - WARN_(d3d_caps)("[Not supported, but pretended to do]\n"); - return WINED3D_OK; - - /* Those are not advertized by the nvidia windows driver, and not - * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap. - * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned - * ARGB format if needed - */ - case WINED3DFMT_W11V11U10: - case WINED3DFMT_A2W10V10U10: - WARN_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - - /***** - * DXTN Formats: Handled above - * WINED3DFMT_DXT1 - * WINED3DFMT_DXT2 - * WINED3DFMT_DXT3 - * WINED3DFMT_DXT4 - * WINED3DFMT_DXT5 - */ - - /***** - * Odd formats - not supported - */ - case WINED3DFMT_VERTEXDATA: - case WINED3DFMT_INDEX16: - case WINED3DFMT_INDEX32: - case WINED3DFMT_Q16W16V16U16: - TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ - return WINED3DERR_NOTAVAILABLE; - - /***** - * Float formats: Not supported right now - */ - case WINED3DFMT_G16R16F: - case WINED3DFMT_G32R32F: - case WINED3DFMT_CxV8U8: - TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ - return WINED3DERR_NOTAVAILABLE; - - /* Not supported */ - case WINED3DFMT_G16R16: - case WINED3DFMT_A16B16G16R16: - case WINED3DFMT_A8R3G3B2: - TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ - return WINED3DERR_NOTAVAILABLE; - - /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support - * instancing. To query if the card supports instancing CheckDeviceFormat with the special format - * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value. - * We can do instancing with all shader versions, but we need vertex shaders. - * - * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once - * to enable instancing. WineD3D doesn't need that and just ignores it. - * - * With Shader Model 3.0 capable cards Instancing 'just works' in Windows. - */ - case WINEMAKEFOURCC('I','N','S','T'): - TRACE("ATI Instancing check hack\n"); - if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) { - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - } else { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - - default: - break; + /* 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)){ + 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]\n"); - return WINED3DERR_NOTAVAILABLE; } static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, @@ -2065,6 +2982,52 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, return WINED3D_OK; } +static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType) { + const shader_backend_t *ret; + int vs_selected_mode; + int ps_selected_mode; + + select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); + if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) { + ret = &glsl_shader_backend; + } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) { + ret = &arb_program_shader_backend; + } else { + ret = &none_shader_backend; + } + return ret; +} + +static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) { + int vs_selected_mode; + int ps_selected_mode; + + select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); + if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + return &arbfp_fragment_pipeline; + } else if(ps_selected_mode == SHADER_ATI) { + return &atifs_fragment_pipeline; + } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) { + return &nvts_fragment_pipeline; + } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) { + return &nvrc_fragment_pipeline; + } else { + return &ffp_fragment_pipeline; + } +} + +static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) { + int vs_selected_mode; + int ps_selected_mode; + + select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); + if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + return &arbfp_blit; + } else { + return &ffp_blit; + } +} + /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true subset of a D3DCAPS9 structure. However, it has to come via a void * as the d3d8 interface cannot import the d3d9 header */ @@ -2073,6 +3036,11 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, IWineD3DImpl *This = (IWineD3DImpl *)iface; int vs_selected_mode; int ps_selected_mode; + struct shader_caps shader_caps; + struct fragment_caps fragment_caps; + const shader_backend_t *shader_backend; + const struct fragment_pipeline *frag_pipeline = NULL; + DWORD ckey_caps, blit_caps, fx_caps; TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps); @@ -2089,84 +3057,78 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, /* ------------------------------------------------ The following fields apply to both d3d8 and d3d9 ------------------------------------------------ */ - *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */ - *pCaps->AdapterOrdinal = Adapter; + pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */ + pCaps->AdapterOrdinal = Adapter; - *pCaps->Caps = 0; - *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED | - WINED3DCAPS2_FULLSCREENGAMMA | - WINED3DCAPS2_DYNAMICTEXTURES; + pCaps->Caps = 0; + pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED | + WINED3DCAPS2_FULLSCREENGAMMA | + WINED3DCAPS2_DYNAMICTEXTURES; if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { - *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP; + pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP; } - *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD; - *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE | - WINED3DPRESENT_INTERVAL_ONE; + pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD; + pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE | + WINED3DPRESENT_INTERVAL_ONE; - *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR | - WINED3DCURSORCAPS_LOWRES; + pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR | + WINED3DCURSORCAPS_LOWRES; - *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX | - WINED3DDEVCAPS_EXECUTESYSTEMMEMORY | - WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY| - WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY | - WINED3DDEVCAPS_DRAWPRIMTLVERTEX | - WINED3DDEVCAPS_HWTRANSFORMANDLIGHT | - WINED3DDEVCAPS_EXECUTEVIDEOMEMORY | - WINED3DDEVCAPS_PUREDEVICE | - WINED3DDEVCAPS_HWRASTERIZATION | - WINED3DDEVCAPS_TEXTUREVIDEOMEMORY | - WINED3DDEVCAPS_TEXTURESYSTEMMEMORY | - WINED3DDEVCAPS_CANRENDERAFTERFLIP | - WINED3DDEVCAPS_DRAWPRIMITIVES2 | - WINED3DDEVCAPS_DRAWPRIMITIVES2EX | - WINED3DDEVCAPS_RTPATCHES; + pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX | + WINED3DDEVCAPS_EXECUTESYSTEMMEMORY | + WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY| + WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY | + WINED3DDEVCAPS_DRAWPRIMTLVERTEX | + WINED3DDEVCAPS_HWTRANSFORMANDLIGHT | + WINED3DDEVCAPS_EXECUTEVIDEOMEMORY | + WINED3DDEVCAPS_PUREDEVICE | + WINED3DDEVCAPS_HWRASTERIZATION | + WINED3DDEVCAPS_TEXTUREVIDEOMEMORY | + WINED3DDEVCAPS_TEXTURESYSTEMMEMORY | + WINED3DDEVCAPS_CANRENDERAFTERFLIP | + WINED3DDEVCAPS_DRAWPRIMITIVES2 | + WINED3DDEVCAPS_DRAWPRIMITIVES2EX | + WINED3DDEVCAPS_RTPATCHES; - *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE | - WINED3DPMISCCAPS_CULLCCW | - WINED3DPMISCCAPS_CULLCW | - WINED3DPMISCCAPS_COLORWRITEENABLE | - WINED3DPMISCCAPS_CLIPTLVERTS | - WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS | - WINED3DPMISCCAPS_MASKZ | - WINED3DPMISCCAPS_BLENDOP; + pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE | + WINED3DPMISCCAPS_CULLCCW | + WINED3DPMISCCAPS_CULLCW | + WINED3DPMISCCAPS_COLORWRITEENABLE | + WINED3DPMISCCAPS_CLIPTLVERTS | + WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS | + WINED3DPMISCCAPS_MASKZ | + WINED3DPMISCCAPS_BLENDOP | + WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING; /* TODO: WINED3DPMISCCAPS_NULLREFERENCE WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS WINED3DPMISCCAPS_FOGANDSPECULARALPHA - WINED3DPMISCCAPS_SEPARATEALPHABLEND WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS - WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING WINED3DPMISCCAPS_FOGVERTEXCLAMPED */ -/* 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_SUPPORT(NV_REGISTER_COMBINERS)) - *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; - if (GL_SUPPORT(NV_REGISTER_COMBINERS2)) - *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; -#endif + if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND; - *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER | - WINED3DPRASTERCAPS_PAT | - WINED3DPRASTERCAPS_WFOG | - WINED3DPRASTERCAPS_ZFOG | - WINED3DPRASTERCAPS_FOGVERTEX | - WINED3DPRASTERCAPS_FOGTABLE | - WINED3DPRASTERCAPS_STIPPLE | - WINED3DPRASTERCAPS_SUBPIXEL | - WINED3DPRASTERCAPS_ZTEST | - WINED3DPRASTERCAPS_SCISSORTEST | - WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS | - WINED3DPRASTERCAPS_DEPTHBIAS; + pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER | + WINED3DPRASTERCAPS_PAT | + WINED3DPRASTERCAPS_WFOG | + WINED3DPRASTERCAPS_ZFOG | + WINED3DPRASTERCAPS_FOGVERTEX | + WINED3DPRASTERCAPS_FOGTABLE | + WINED3DPRASTERCAPS_STIPPLE | + WINED3DPRASTERCAPS_SUBPIXEL | + WINED3DPRASTERCAPS_ZTEST | + WINED3DPRASTERCAPS_SCISSORTEST | + WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS | + WINED3DPRASTERCAPS_DEPTHBIAS; if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) { - *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY | - WINED3DPRASTERCAPS_ZBIAS | - WINED3DPRASTERCAPS_MIPMAPLODBIAS; + pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY | + WINED3DPRASTERCAPS_ZBIAS | + WINED3DPRASTERCAPS_MIPMAPLODBIAS; } if(GL_SUPPORT(NV_FOG_DISTANCE)) { - *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE; + pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE; } /* FIXME Add: WINED3DPRASTERCAPS_COLORPERSPECTIVE @@ -2175,41 +3137,39 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DPRASTERCAPS_ZBUFFERLESSHSR WINED3DPRASTERCAPS_WBUFFER */ - *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS | - WINED3DPCMPCAPS_EQUAL | - WINED3DPCMPCAPS_GREATER | - WINED3DPCMPCAPS_GREATEREQUAL | - WINED3DPCMPCAPS_LESS | - WINED3DPCMPCAPS_LESSEQUAL | - WINED3DPCMPCAPS_NEVER | - WINED3DPCMPCAPS_NOTEQUAL; + pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS | + WINED3DPCMPCAPS_EQUAL | + WINED3DPCMPCAPS_GREATER | + WINED3DPCMPCAPS_GREATEREQUAL | + WINED3DPCMPCAPS_LESS | + WINED3DPCMPCAPS_LESSEQUAL | + WINED3DPCMPCAPS_NEVER | + WINED3DPCMPCAPS_NOTEQUAL; - *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR | - WINED3DPBLENDCAPS_BOTHINVSRCALPHA | - WINED3DPBLENDCAPS_BOTHSRCALPHA | - WINED3DPBLENDCAPS_DESTALPHA | - WINED3DPBLENDCAPS_DESTCOLOR | - WINED3DPBLENDCAPS_INVDESTALPHA | - WINED3DPBLENDCAPS_INVDESTCOLOR | - WINED3DPBLENDCAPS_INVSRCALPHA | - WINED3DPBLENDCAPS_INVSRCCOLOR | - WINED3DPBLENDCAPS_ONE | - WINED3DPBLENDCAPS_SRCALPHA | - WINED3DPBLENDCAPS_SRCALPHASAT | - WINED3DPBLENDCAPS_SRCCOLOR | - WINED3DPBLENDCAPS_ZERO; + pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA | + WINED3DPBLENDCAPS_BOTHSRCALPHA | + WINED3DPBLENDCAPS_DESTALPHA | + WINED3DPBLENDCAPS_DESTCOLOR | + WINED3DPBLENDCAPS_INVDESTALPHA | + WINED3DPBLENDCAPS_INVDESTCOLOR | + WINED3DPBLENDCAPS_INVSRCALPHA | + WINED3DPBLENDCAPS_INVSRCCOLOR | + WINED3DPBLENDCAPS_ONE | + WINED3DPBLENDCAPS_SRCALPHA | + WINED3DPBLENDCAPS_SRCALPHASAT | + WINED3DPBLENDCAPS_SRCCOLOR | + WINED3DPBLENDCAPS_ZERO; - *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR | - WINED3DPBLENDCAPS_DESTALPHA | - WINED3DPBLENDCAPS_DESTCOLOR | - WINED3DPBLENDCAPS_INVDESTALPHA | - WINED3DPBLENDCAPS_INVDESTCOLOR | - WINED3DPBLENDCAPS_INVSRCALPHA | - WINED3DPBLENDCAPS_INVSRCCOLOR | - WINED3DPBLENDCAPS_ONE | - WINED3DPBLENDCAPS_SRCALPHA | - WINED3DPBLENDCAPS_SRCCOLOR | - WINED3DPBLENDCAPS_ZERO; + pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA | + WINED3DPBLENDCAPS_DESTCOLOR | + WINED3DPBLENDCAPS_INVDESTALPHA | + WINED3DPBLENDCAPS_INVDESTCOLOR | + WINED3DPBLENDCAPS_INVSRCALPHA | + WINED3DPBLENDCAPS_INVSRCCOLOR | + WINED3DPBLENDCAPS_ONE | + WINED3DPBLENDCAPS_SRCALPHA | + WINED3DPBLENDCAPS_SRCCOLOR | + WINED3DPBLENDCAPS_ZERO; /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor, * according to the glBlendFunc manpage * @@ -2217,452 +3177,428 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, * legacy settings for srcblend only */ - *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS | - WINED3DPCMPCAPS_EQUAL | - WINED3DPCMPCAPS_GREATER | - WINED3DPCMPCAPS_GREATEREQUAL | - WINED3DPCMPCAPS_LESS | - WINED3DPCMPCAPS_LESSEQUAL | - WINED3DPCMPCAPS_NEVER | - WINED3DPCMPCAPS_NOTEQUAL; + if( GL_SUPPORT(EXT_BLEND_COLOR)) { + pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR; + pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR; + } - *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB | - WINED3DPSHADECAPS_COLORGOURAUDRGB | - WINED3DPSHADECAPS_ALPHAFLATBLEND | - WINED3DPSHADECAPS_ALPHAGOURAUDBLEND | - WINED3DPSHADECAPS_COLORFLATRGB | - WINED3DPSHADECAPS_FOGFLAT | - WINED3DPSHADECAPS_FOGGOURAUD | - WINED3DPSHADECAPS_SPECULARFLATRGB; - *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA | - WINED3DPTEXTURECAPS_ALPHAPALETTE | - WINED3DPTEXTURECAPS_BORDER | - WINED3DPTEXTURECAPS_MIPMAP | - WINED3DPTEXTURECAPS_PROJECTED | - WINED3DPTEXTURECAPS_PERSPECTIVE; + pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS | + WINED3DPCMPCAPS_EQUAL | + WINED3DPCMPCAPS_GREATER | + WINED3DPCMPCAPS_GREATEREQUAL | + WINED3DPCMPCAPS_LESS | + WINED3DPCMPCAPS_LESSEQUAL | + WINED3DPCMPCAPS_NEVER | + WINED3DPCMPCAPS_NOTEQUAL; + + pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB | + WINED3DPSHADECAPS_COLORGOURAUDRGB | + WINED3DPSHADECAPS_ALPHAFLATBLEND | + WINED3DPSHADECAPS_ALPHAGOURAUDBLEND | + WINED3DPSHADECAPS_COLORFLATRGB | + WINED3DPSHADECAPS_FOGFLAT | + WINED3DPSHADECAPS_FOGGOURAUD | + WINED3DPSHADECAPS_SPECULARFLATRGB; + + pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA | + WINED3DPTEXTURECAPS_ALPHAPALETTE | + WINED3DPTEXTURECAPS_TRANSPARENCY | + WINED3DPTEXTURECAPS_BORDER | + WINED3DPTEXTURECAPS_MIPMAP | + WINED3DPTEXTURECAPS_PROJECTED | + WINED3DPTEXTURECAPS_PERSPECTIVE; if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { - *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 | - WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL; + pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 | + WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL; } if( GL_SUPPORT(EXT_TEXTURE3D)) { - *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP | - WINED3DPTEXTURECAPS_MIPVOLUMEMAP | - WINED3DPTEXTURECAPS_VOLUMEMAP_POW2; + pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP | + WINED3DPTEXTURECAPS_MIPVOLUMEMAP | + WINED3DPTEXTURECAPS_VOLUMEMAP_POW2; } if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { - *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP | - WINED3DPTEXTURECAPS_MIPCUBEMAP | - WINED3DPTEXTURECAPS_CUBEMAP_POW2; + pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP | + WINED3DPTEXTURECAPS_MIPCUBEMAP | + WINED3DPTEXTURECAPS_CUBEMAP_POW2; } - *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | - WINED3DPTFILTERCAPS_MAGFPOINT | - WINED3DPTFILTERCAPS_MINFLINEAR | - WINED3DPTFILTERCAPS_MINFPOINT | - WINED3DPTFILTERCAPS_MIPFLINEAR | - WINED3DPTFILTERCAPS_MIPFPOINT | - WINED3DPTFILTERCAPS_LINEAR | - WINED3DPTFILTERCAPS_LINEARMIPLINEAR | - WINED3DPTFILTERCAPS_LINEARMIPNEAREST | - WINED3DPTFILTERCAPS_MIPLINEAR | - WINED3DPTFILTERCAPS_MIPNEAREST | - WINED3DPTFILTERCAPS_NEAREST; + pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | + WINED3DPTFILTERCAPS_MAGFPOINT | + WINED3DPTFILTERCAPS_MINFLINEAR | + WINED3DPTFILTERCAPS_MINFPOINT | + WINED3DPTFILTERCAPS_MIPFLINEAR | + WINED3DPTFILTERCAPS_MIPFPOINT | + WINED3DPTFILTERCAPS_LINEAR | + WINED3DPTFILTERCAPS_LINEARMIPLINEAR | + WINED3DPTFILTERCAPS_LINEARMIPNEAREST | + WINED3DPTFILTERCAPS_MIPLINEAR | + WINED3DPTFILTERCAPS_MIPNEAREST | + WINED3DPTFILTERCAPS_NEAREST; if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) { - *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC | - WINED3DPTFILTERCAPS_MINFANISOTROPIC; + pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC | + WINED3DPTFILTERCAPS_MINFANISOTROPIC; } if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { - *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | - WINED3DPTFILTERCAPS_MAGFPOINT | - WINED3DPTFILTERCAPS_MINFLINEAR | - WINED3DPTFILTERCAPS_MINFPOINT | - WINED3DPTFILTERCAPS_MIPFLINEAR | - WINED3DPTFILTERCAPS_MIPFPOINT | - WINED3DPTFILTERCAPS_LINEAR | - WINED3DPTFILTERCAPS_LINEARMIPLINEAR | - WINED3DPTFILTERCAPS_LINEARMIPNEAREST | - WINED3DPTFILTERCAPS_MIPLINEAR | - WINED3DPTFILTERCAPS_MIPNEAREST | - WINED3DPTFILTERCAPS_NEAREST; + pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | + WINED3DPTFILTERCAPS_MAGFPOINT | + WINED3DPTFILTERCAPS_MINFLINEAR | + WINED3DPTFILTERCAPS_MINFPOINT | + WINED3DPTFILTERCAPS_MIPFLINEAR | + WINED3DPTFILTERCAPS_MIPFPOINT | + WINED3DPTFILTERCAPS_LINEAR | + WINED3DPTFILTERCAPS_LINEARMIPLINEAR | + WINED3DPTFILTERCAPS_LINEARMIPNEAREST | + WINED3DPTFILTERCAPS_MIPLINEAR | + WINED3DPTFILTERCAPS_MIPNEAREST | + WINED3DPTFILTERCAPS_NEAREST; if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) { - *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC | + pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC | WINED3DPTFILTERCAPS_MINFANISOTROPIC; } } else - *pCaps->CubeTextureFilterCaps = 0; + pCaps->CubeTextureFilterCaps = 0; if (GL_SUPPORT(EXT_TEXTURE3D)) { - *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | - WINED3DPTFILTERCAPS_MAGFPOINT | - WINED3DPTFILTERCAPS_MINFLINEAR | - WINED3DPTFILTERCAPS_MINFPOINT | - WINED3DPTFILTERCAPS_MIPFLINEAR | - WINED3DPTFILTERCAPS_MIPFPOINT | - WINED3DPTFILTERCAPS_LINEAR | - WINED3DPTFILTERCAPS_LINEARMIPLINEAR | - WINED3DPTFILTERCAPS_LINEARMIPNEAREST | - WINED3DPTFILTERCAPS_MIPLINEAR | - WINED3DPTFILTERCAPS_MIPNEAREST | - WINED3DPTFILTERCAPS_NEAREST; + pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR | + WINED3DPTFILTERCAPS_MAGFPOINT | + WINED3DPTFILTERCAPS_MINFLINEAR | + WINED3DPTFILTERCAPS_MINFPOINT | + WINED3DPTFILTERCAPS_MIPFLINEAR | + WINED3DPTFILTERCAPS_MIPFPOINT | + WINED3DPTFILTERCAPS_LINEAR | + WINED3DPTFILTERCAPS_LINEARMIPLINEAR | + WINED3DPTFILTERCAPS_LINEARMIPNEAREST | + WINED3DPTFILTERCAPS_MIPLINEAR | + WINED3DPTFILTERCAPS_MIPNEAREST | + WINED3DPTFILTERCAPS_NEAREST; } else - *pCaps->VolumeTextureFilterCaps = 0; + pCaps->VolumeTextureFilterCaps = 0; - *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV | - WINED3DPTADDRESSCAPS_CLAMP | - WINED3DPTADDRESSCAPS_WRAP; + pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV | + WINED3DPTADDRESSCAPS_CLAMP | + WINED3DPTADDRESSCAPS_WRAP; if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) { - *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER; + pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER; } if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) { - *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR; + pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR; } if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) { - *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE; + pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE; } if (GL_SUPPORT(EXT_TEXTURE3D)) { - *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV | - WINED3DPTADDRESSCAPS_CLAMP | - WINED3DPTADDRESSCAPS_WRAP; + pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV | + WINED3DPTADDRESSCAPS_CLAMP | + WINED3DPTADDRESSCAPS_WRAP; if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) { - *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER; + pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER; } if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) { - *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR; + pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR; } if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) { - *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE; + pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE; } } else - *pCaps->VolumeTextureAddressCaps = 0; + pCaps->VolumeTextureAddressCaps = 0; - *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE | - WINED3DLINECAPS_ZTEST; - /* FIXME: Add - WINED3DLINECAPS_BLEND - WINED3DLINECAPS_ALPHACMP - WINED3DLINECAPS_FOG */ + pCaps->LineCaps = WINED3DLINECAPS_TEXTURE | + WINED3DLINECAPS_ZTEST | + WINED3DLINECAPS_BLEND | + WINED3DLINECAPS_ALPHACMP | + WINED3DLINECAPS_FOG; + /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different + * idea how generating the smoothing alpha values works; the result is different + */ - *pCaps->MaxTextureWidth = GL_LIMITS(texture_size); - *pCaps->MaxTextureHeight = GL_LIMITS(texture_size); + pCaps->MaxTextureWidth = GL_LIMITS(texture_size); + pCaps->MaxTextureHeight = GL_LIMITS(texture_size); if(GL_SUPPORT(EXT_TEXTURE3D)) - *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size); + pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size); else - *pCaps->MaxVolumeExtent = 0; + pCaps->MaxVolumeExtent = 0; - *pCaps->MaxTextureRepeat = 32768; - *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size); - *pCaps->MaxVertexW = 1.0; + pCaps->MaxTextureRepeat = 32768; + pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size); + pCaps->MaxVertexW = 1.0; - *pCaps->GuardBandLeft = 0; - *pCaps->GuardBandTop = 0; - *pCaps->GuardBandRight = 0; - *pCaps->GuardBandBottom = 0; + pCaps->GuardBandLeft = 0; + pCaps->GuardBandTop = 0; + pCaps->GuardBandRight = 0; + pCaps->GuardBandBottom = 0; - *pCaps->ExtentsAdjust = 0; + pCaps->ExtentsAdjust = 0; - *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT | - WINED3DSTENCILCAPS_INCRSAT | - WINED3DSTENCILCAPS_INVERT | - WINED3DSTENCILCAPS_KEEP | - WINED3DSTENCILCAPS_REPLACE | - WINED3DSTENCILCAPS_ZERO; + pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT | + WINED3DSTENCILCAPS_INCRSAT | + WINED3DSTENCILCAPS_INVERT | + WINED3DSTENCILCAPS_KEEP | + WINED3DSTENCILCAPS_REPLACE | + WINED3DSTENCILCAPS_ZERO; if (GL_SUPPORT(EXT_STENCIL_WRAP)) { - *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR | - WINED3DSTENCILCAPS_INCR; + pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR | + WINED3DSTENCILCAPS_INCR; } if ( This->dxVersion > 8 && ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) { - *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED; + pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED; } - *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */ + pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */ - *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | - WINED3DTEXOPCAPS_ADDSIGNED | - WINED3DTEXOPCAPS_ADDSIGNED2X | - WINED3DTEXOPCAPS_MODULATE | - WINED3DTEXOPCAPS_MODULATE2X | - WINED3DTEXOPCAPS_MODULATE4X | - WINED3DTEXOPCAPS_SELECTARG1 | - WINED3DTEXOPCAPS_SELECTARG2 | - WINED3DTEXOPCAPS_DISABLE; + pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes); + pCaps->MaxActiveLights = GL_LIMITS(lights); - if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) || - GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) || - GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | - WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | - WINED3DTEXOPCAPS_BLENDFACTORALPHA | - WINED3DTEXOPCAPS_BLENDCURRENTALPHA | - WINED3DTEXOPCAPS_LERP | - WINED3DTEXOPCAPS_SUBTRACT; - } - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) || - GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH | - WINED3DTEXOPCAPS_MULTIPLYADD | - WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | - WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | - WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM; - } - if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3; + pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends); + pCaps->MaxVertexBlendMatrixIndex = 0; - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | - WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA; - } - - if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP; - } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does - * not support 3D textures. This asks for trouble if an app uses both bump mapping - * and 3D textures. It also allows us to keep the code simpler by having texture - * shaders constantly enabled. - */ - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP; - /* TODO: Luminance bump map? */ - } -#if 0 - /* FIXME: Add - *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE - WINED3DTEXOPCAPS_PREMODULATE */ -#endif - - *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages); - *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures); - *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes); - *pCaps->MaxActiveLights = GL_LIMITS(lights); - - *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends); - *pCaps->MaxVertexBlendMatrixIndex = 0; - - *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy); - *pCaps->MaxPointSize = GL_LIMITS(pointsize); + pCaps->MaxAnisotropy = GL_LIMITS(anisotropy); + pCaps->MaxPointSize = GL_LIMITS(pointsize); - *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS | - WINED3DVTXPCAPS_MATERIALSOURCE7 | - WINED3DVTXPCAPS_POSITIONALLIGHTS | - WINED3DVTXPCAPS_LOCALVIEWER | - WINED3DVTXPCAPS_VERTEXFOG | - WINED3DVTXPCAPS_TEXGEN; + pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS | + WINED3DVTXPCAPS_MATERIALSOURCE7 | + WINED3DVTXPCAPS_POSITIONALLIGHTS | + WINED3DVTXPCAPS_LOCALVIEWER | + WINED3DVTXPCAPS_VERTEXFOG | + WINED3DVTXPCAPS_TEXGEN; /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */ - *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */ - *pCaps->MaxVertexIndex = 0xFFFFF; - *pCaps->MaxStreams = MAX_STREAMS; - *pCaps->MaxStreamStride = 1024; + pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */ + pCaps->MaxVertexIndex = 0xFFFFF; + pCaps->MaxStreams = MAX_STREAMS; + pCaps->MaxStreamStride = 1024; - if (vs_selected_mode == SHADER_GLSL) { - /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati - * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using - * vs_nv_version which is based on NV_vertex_program. - * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not - * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it - * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number - * of native instructions, so use that here. For more info see the pixel shader versioning code below. */ - if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512)) - *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0); - else - *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); - TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff); - } else if (vs_selected_mode == SHADER_ARB) { - *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1); - TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n"); + /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */ + pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET | + WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET; + pCaps->MaxNpatchTessellationLevel = 0; + pCaps->MasterAdapterOrdinal = 0; + pCaps->AdapterOrdinalInGroup = 0; + pCaps->NumberOfAdaptersInGroup = 1; + + pCaps->NumSimultaneousRTs = GL_LIMITS(buffers); + + pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT | + WINED3DPTFILTERCAPS_MAGFPOINT | + WINED3DPTFILTERCAPS_MINFLINEAR | + WINED3DPTFILTERCAPS_MAGFLINEAR; + pCaps->VertexTextureFilterCaps = 0; + + memset(&shader_caps, 0, sizeof(shader_caps)); + shader_backend = select_shader_backend(Adapter, DeviceType); + shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps); + + memset(&fragment_caps, 0, sizeof(fragment_caps)); + frag_pipeline = select_fragment_implementation(Adapter, DeviceType); + frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &fragment_caps); + + /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */ + pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps; + + /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled. + * Ignore shader model capabilities if disabled in config + */ + if(vs_selected_mode == SHADER_NONE) { + TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n"); + pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0); + pCaps->MaxVertexShaderConst = 0; } else { - *pCaps->VertexShaderVersion = 0; - TRACE_(d3d_caps)("Vertex shader functionality not available\n"); + pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion; + pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst; } - *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF); - - if (ps_selected_mode == SHADER_GLSL) { - /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b. - * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed - * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment - * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info - * in max native instructions. Intel and others also offer the info in this extension but they - * don't support GLSL (at least on Windows). - * - * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number - * of instructions is 512 or less we have to do with ps2.0 hardware. - * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware. - */ - if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512)) - *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0); - else - *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); - /* FIXME: The following line is card dependent. -8.0 to 8.0 is the - * Direct3D minimum requirement. - * - * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude" - * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here? - * - * The problem is that the refrast clamps temporary results in the shader to - * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here, - * then applications may miss the clamping behavior. On the other hand, if it is smaller, - * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't - * offer a way to query this. - */ - *pCaps->PixelShader1xMaxValue = 8.0; - TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff); - } else if (ps_selected_mode == SHADER_ARB) { - *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4); - *pCaps->PixelShader1xMaxValue = 8.0; - TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n"); + if(ps_selected_mode == SHADER_NONE) { + TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n"); + pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0); + pCaps->PixelShader1xMaxValue = 0.0; } else { - *pCaps->PixelShaderVersion = 0; - *pCaps->PixelShader1xMaxValue = 0.0; - TRACE_(d3d_caps)("Pixel shader functionality not available\n"); + pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion; + pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue; } - /* ------------------------------------------------ - The following fields apply to d3d9 only - ------------------------------------------------ */ - if (This->dxVersion > 8) { - /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */ - *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET; - /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */ - *pCaps->MaxNpatchTessellationLevel = 0; - *pCaps->MasterAdapterOrdinal = 0; - *pCaps->AdapterOrdinalInGroup = 0; - *pCaps->NumberOfAdaptersInGroup = 1; + pCaps->TextureOpCaps = fragment_caps.TextureOpCaps; + pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages; + pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures; - if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) { - /* OpenGL supports all the formats below, perhaps not always - * without conversion, but it supports them. - * Further GLSL doesn't seem to have an official unsigned type so - * don't advertise it yet as I'm not sure how we handle it. - * We might need to add some clamping in the shader engine to - * support it. - * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */ - *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 | - WINED3DDTCAPS_UBYTE4N | - WINED3DDTCAPS_SHORT2N | - WINED3DDTCAPS_SHORT4N; - if (GL_SUPPORT(NV_HALF_FLOAT)) { - *pCaps->DeclTypes |= - WINED3DDTCAPS_FLOAT16_2 | + 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 + */ + if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) { + /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering) + use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */ + pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION; + pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */ + pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps); + pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */ + + pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */ + pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions); + } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) { + pCaps->VS20Caps.Caps = 0; + pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH; + pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps); + pCaps->VS20Caps.StaticFlowControlDepth = 1; + + pCaps->MaxVShaderInstructionsExecuted = 65535; + pCaps->MaxVertexShader30InstructionSlots = 0; + } else { /* VS 1.x */ + pCaps->VS20Caps.Caps = 0; + pCaps->VS20Caps.DynamicFlowControlDepth = 0; + pCaps->VS20Caps.NumTemps = 0; + pCaps->VS20Caps.StaticFlowControlDepth = 0; + + pCaps->MaxVShaderInstructionsExecuted = 0; + pCaps->MaxVertexShader30InstructionSlots = 0; + } + + if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) { + /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering) + use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */ + + /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */ + pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE | + WINED3DPS20CAPS_GRADIENTINSTRUCTIONS | + WINED3DPS20CAPS_PREDICATION | + WINED3DPS20CAPS_NODEPENDENTREADLIMIT | + WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT; + pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */ + pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps); + pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */ + pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */ + + pCaps->MaxPShaderInstructionsExecuted = 65535; + pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions); + } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) { + /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */ + pCaps->PS20Caps.Caps = 0; + pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */ + pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps); + pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */ + pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */ + + pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */ + pCaps->MaxPixelShader30InstructionSlots = 0; + } else { /* PS 1.x */ + pCaps->PS20Caps.Caps = 0; + pCaps->PS20Caps.DynamicFlowControlDepth = 0; + pCaps->PS20Caps.NumTemps = 0; + pCaps->PS20Caps.StaticFlowControlDepth = 0; + pCaps->PS20Caps.NumInstructionSlots = 0; + + pCaps->MaxPShaderInstructionsExecuted = 0; + pCaps->MaxPixelShader30InstructionSlots = 0; + } + + if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) { + /* OpenGL supports all the formats below, perhaps not always + * without conversion, but it supports them. + * Further GLSL doesn't seem to have an official unsigned type so + * don't advertise it yet as I'm not sure how we handle it. + * We might need to add some clamping in the shader engine to + * support it. + * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */ + pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 | + WINED3DDTCAPS_UBYTE4N | + WINED3DDTCAPS_SHORT2N | + WINED3DDTCAPS_SHORT4N; + if (GL_SUPPORT(NV_HALF_FLOAT)) { + pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4; - } - } else - *pCaps->DeclTypes = 0; - - *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers); - - - *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT | - WINED3DPTFILTERCAPS_MAGFPOINT | - WINED3DPTFILTERCAPS_MINFLINEAR | - WINED3DPTFILTERCAPS_MAGFLINEAR; - *pCaps->VertexTextureFilterCaps = 0; - - if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) { - /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering) - use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */ - *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION; - *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */ - *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps); - *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */ - - *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */ - *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions); - } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) { - *pCaps->VS20Caps.Caps = 0; - *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH; - *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps); - *pCaps->VS20Caps.StaticFlowControlDepth = 1; - - *pCaps->MaxVShaderInstructionsExecuted = 65535; - *pCaps->MaxVertexShader30InstructionSlots = 0; - } else { /* VS 1.x */ - *pCaps->VS20Caps.Caps = 0; - *pCaps->VS20Caps.DynamicFlowControlDepth = 0; - *pCaps->VS20Caps.NumTemps = 0; - *pCaps->VS20Caps.StaticFlowControlDepth = 0; - - *pCaps->MaxVShaderInstructionsExecuted = 0; - *pCaps->MaxVertexShader30InstructionSlots = 0; } + } else + pCaps->DeclTypes = 0; - if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) { - /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering) - use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */ - - /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */ - *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE | - WINED3DPS20CAPS_GRADIENTINSTRUCTIONS | - WINED3DPS20CAPS_PREDICATION | - WINED3DPS20CAPS_NODEPENDENTREADLIMIT | - WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT; - *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */ - *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps); - *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */ - *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */ + /* Set DirectDraw helper Caps */ + ckey_caps = WINEDDCKEYCAPS_DESTBLT | + WINEDDCKEYCAPS_SRCBLT; + fx_caps = WINEDDFXCAPS_BLTALPHA | + WINEDDFXCAPS_BLTMIRRORLEFTRIGHT | + WINEDDFXCAPS_BLTMIRRORUPDOWN | + WINEDDFXCAPS_BLTROTATION90 | + WINEDDFXCAPS_BLTSHRINKX | + WINEDDFXCAPS_BLTSHRINKXN | + WINEDDFXCAPS_BLTSHRINKY | + WINEDDFXCAPS_BLTSHRINKXN | + WINEDDFXCAPS_BLTSTRETCHX | + WINEDDFXCAPS_BLTSTRETCHXN | + WINEDDFXCAPS_BLTSTRETCHY | + WINEDDFXCAPS_BLTSTRETCHYN; + blit_caps = WINEDDCAPS_BLT | + WINEDDCAPS_BLTCOLORFILL | + WINEDDCAPS_BLTDEPTHFILL | + WINEDDCAPS_BLTSTRETCH | + WINEDDCAPS_CANBLTSYSMEM | + WINEDDCAPS_CANCLIP | + WINEDDCAPS_CANCLIPSTRETCHED | + WINEDDCAPS_COLORKEY | + WINEDDCAPS_COLORKEYHWASSIST | + WINEDDCAPS_ALIGNBOUNDARYSRC; - *pCaps->MaxPShaderInstructionsExecuted = 65535; - *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions); - } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) { - /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */ - *pCaps->PS20Caps.Caps = 0; - *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */ - *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps); - *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */ - *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */ + /* Fill the ddraw caps structure */ + pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI | + WINEDDCAPS_PALETTE | + blit_caps; + pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED | + WINEDDCAPS2_NOPAGELOCKREQUIRED | + WINEDDCAPS2_PRIMARYGAMMA | + WINEDDCAPS2_WIDESURFACES | + WINEDDCAPS2_CANRENDERWINDOWED; + pCaps->DirectDrawCaps.SVBCaps = blit_caps; + pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps; + pCaps->DirectDrawCaps.SVBFXCaps = fx_caps; + pCaps->DirectDrawCaps.VSBCaps = blit_caps; + pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps; + pCaps->DirectDrawCaps.VSBFXCaps = fx_caps; + pCaps->DirectDrawCaps.SSBCaps = blit_caps; + pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps; + pCaps->DirectDrawCaps.SSBFXCaps = fx_caps; - *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */ - *pCaps->MaxPixelShader30InstructionSlots = 0; - } else { /* PS 1.x */ - *pCaps->PS20Caps.Caps = 0; - *pCaps->PS20Caps.DynamicFlowControlDepth = 0; - *pCaps->PS20Caps.NumTemps = 0; - *pCaps->PS20Caps.StaticFlowControlDepth = 0; - *pCaps->PS20Caps.NumInstructionSlots = 0; + pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA | + WINEDDSCAPS_BACKBUFFER | + WINEDDSCAPS_FLIP | + WINEDDSCAPS_FRONTBUFFER | + WINEDDSCAPS_OFFSCREENPLAIN | + WINEDDSCAPS_PALETTE | + WINEDDSCAPS_PRIMARYSURFACE | + WINEDDSCAPS_SYSTEMMEMORY | + WINEDDSCAPS_VIDEOMEMORY | + WINEDDSCAPS_VISIBLE; + pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT; - *pCaps->MaxPShaderInstructionsExecuted = 0; - *pCaps->MaxPixelShader30InstructionSlots = 0; - } + /* Set D3D caps if OpenGL is available. */ + if(Adapters[Adapter].opengl) { + pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE | + WINEDDSCAPS_MIPMAP | + WINEDDSCAPS_TEXTURE | + WINEDDSCAPS_ZBUFFER; + pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D; } return WINED3D_OK; } -static unsigned int glsl_program_key_hash(void *key) { - glsl_program_key_t *k = (glsl_program_key_t *)key; - - unsigned int hash = k->vshader | k->pshader << 16; - hash += ~(hash << 15); - hash ^= (hash >> 10); - hash += (hash << 3); - hash ^= (hash >> 6); - hash += ~(hash << 11); - hash ^= (hash >> 16); - - return hash; -} - -static BOOL glsl_program_key_compare(void *keya, void *keyb) { - glsl_program_key_t *ka = (glsl_program_key_t *)keya; - glsl_program_key_t *kb = (glsl_program_key_t *)keyb; - - return ka->vshader == kb->vshader && ka->pshader == kb->pshader; -} - /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS, and fields being inserted in the middle, a new structure is used in place */ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow, @@ -2671,8 +3607,10 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, IWineD3DDeviceImpl *object = NULL; IWineD3DImpl *This = (IWineD3DImpl *)iface; - HDC hDC; + WINED3DDISPLAYMODE mode; + const struct fragment_pipeline *frag_pipeline = NULL; int i; + struct fragment_caps ffp_caps; /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter * number and create a device without a 3D adapter for 2D only operation. @@ -2697,11 +3635,12 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, IWineD3D_AddRef(object->wineD3D); object->parent = parent; list_init(&object->resources); + list_init(&object->shaders); if(This->dxVersion == 7) { - object->surface_alignment = 8; + object->surface_alignment = DDRAW_PITCH_ALIGNMENT; } else { - object->surface_alignment = 4; + object->surface_alignment = D3D8_PITCH_ALIGNMENT; } object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */ @@ -2722,24 +3661,36 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, object->devType = DeviceType; select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode); - if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) { - object->shader_backend = &glsl_shader_backend; - object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare); - } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) { - object->shader_backend = &arb_program_shader_backend; - } else { - object->shader_backend = &none_shader_backend; + object->shader_backend = select_shader_backend(Adapter, DeviceType); + + memset(&ffp_caps, 0, sizeof(ffp_caps)); + frag_pipeline = select_fragment_implementation(Adapter, DeviceType); + object->frag_pipe = frag_pipeline; + frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps); + object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures; + object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages; + compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION, + ffp_vertexstate_template, frag_pipeline, misc_state_template); + + object->blitter = select_blit_implementation(Adapter, DeviceType); + + /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader + * model can deal with that. It is essentially the same, just with adjusted + * Set*ShaderConstantF implementations + */ + if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) { + object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl; } /* set the state of the device to valid */ object->state = WINED3D_OK; /* Get the initial screen setup for ddraw */ - object->ddraw_width = GetSystemMetrics(SM_CXSCREEN); - object->ddraw_height = GetSystemMetrics(SM_CYSCREEN); - hDC = GetDC(0); - object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)); - ReleaseDC(0, hDC); + IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode); + + object->ddraw_width = mode.Width; + object->ddraw_height = mode.Height; + object->ddraw_format = mode.Format; for(i = 0; i < PATCHMAP_SIZE; i++) { list_init(&object->patches[i]); @@ -2784,8 +3735,8 @@ static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) { * aren't sufficient either because a Linux binary may display on a macos X server via remote X11. * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions * like client storage might be supported on other implementations too, but GL_APPLE_flush_render - * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so - * it the chance that other implementations support it is rather rare since Win32 Quicktime uses + * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So + * the chance that other implementations support them is rather small since Win32 QuickTime uses * DirectDraw, not OpenGL. */ if(gl_info->supported[APPLE_FENCE] && @@ -2802,9 +3753,119 @@ static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) { } } +#define GLINFO_LOCATION (*gl_info) +static void test_pbo_functionality(WineD3D_GL_Info *gl_info) { + /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs, + * but glTexSubImage from a PBO fails miserably, with the first line repeated over + * all the texture. This function detects this bug by its symptom and disables PBOs + * if the test fails. + * + * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA, + * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use + * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data + * read back is compared to the original. If they are equal PBOs are assumed to work, + * otherwise the PBO extension is disabled. + */ + GLuint texture, pbo; + static const unsigned int pattern[] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000, + 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff, + 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff, + 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff + }; + unsigned int check[sizeof(pattern) / sizeof(pattern[0])]; + + if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) { + /* No PBO -> No point in testing them */ + return; + } + + while(glGetError()); + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); + checkGLcall("Specifying the PBO test texture\n"); + + GL_EXTCALL(glGenBuffersARB(1, &pbo)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo)); + GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB)); + checkGLcall("Specifying the PBO test pbo\n"); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + checkGLcall("Loading the PBO test texture\n"); + + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + glFinish(); /* just to be sure */ + + memset(check, 0, sizeof(check)); + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check); + checkGLcall("Reading back the PBO test texture\n"); + + glDeleteTextures(1, &texture); + GL_EXTCALL(glDeleteBuffersARB(1, &pbo)); + checkGLcall("PBO test cleanup\n"); + + if(memcmp(check, pattern, sizeof(check)) != 0) { + WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n"); + WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n"); + gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE; + } else { + TRACE_(d3d_caps)("PBO test successful\n"); + } +} +#undef GLINFO_LOCATION + +/* Certain applications(Steam) complain if we report an outdated driver version. In general, + * reporting a driver version is moot because we are not the Windows driver, and we have different + * bugs, features, etc. + * + * If a card is not found in this table, the gl driver version is reported + */ +struct driver_version_information { + WORD vendor; /* reported PCI card vendor ID */ + WORD card; /* reported PCI card device ID */ + WORD hipart_hi, hipart_lo; /* driver hiword to report */ + WORD lopart_hi, lopart_lo; /* driver loword to report */ +}; + +static const struct driver_version_information driver_version_table[] = { + /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/ + /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */ + /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */ + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 }, + + /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */ + {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 }, + + /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */ +}; + static void fixup_extensions(WineD3D_GL_Info *gl_info) { - if(implementation_is_apple(gl_info)) { - /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are + unsigned int i; + BOOL apple = implementation_is_apple(gl_info); + + if(apple) { + /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are * used it falls back to software. While the compiler can detect if the shader uses all declared * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader * using relative addressing falls back to software. @@ -2819,33 +3880,237 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) { gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF; } - /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although - * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL). - * If real NP2 textures are used, the driver falls back to software. So remove the supported - * flag for this extension + /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems + * with fixed function fragment processing. Ideally this flag should be detected with a test shader + * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones) + * do not like vertex shaders in feedback mode and return an error, even though it should be valid + * according to the spec. + * + * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This + * makes the shader slower and eats instruction slots which should be available to the d3d app. + * + * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist + * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If + * this workaround is activated on cards that do not need it, it won't break things, just affect + * performance negatively. */ - if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) { - if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 || - gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 || - gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) { - TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n"); - gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE; - } + if(gl_info->gl_vendor == VENDOR_INTEL || + (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) { + TRACE("Enabling vertex texture coord fixes in vertex shaders\n"); + gl_info->set_texcoord_w = TRUE; + } + } + + /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although + * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL). + * If real NP2 textures are used, the driver falls back to software. We could just remove the + * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient + * due to the non-normalized texture coordinates. Thus set an internal extension flag, + * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures + * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits. + * + * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which + * has this extension promoted to core. The extension loading code sets this extension supported + * due to that, so this code works on fglrx as well. + */ + if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) { + if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 || + gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 || + gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) { + TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n"); + gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE; + gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE; + } + } + + /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but + * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string. + * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying + * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the + * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used. + * We therefore completely remove ARB_tex_npot from the list of supported extensions. + * + * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot, + * triggering the software fallback. There is not much we can do here apart from disabling the + * software-emulated extension and reenable ARB_tex_rect (which was previously disabled + * in IWineD3DImpl_FillGLCaps). + * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer + * post-processing effects in the game "Max Payne 2"). + * The behaviour can be verified through a simple test app attached in bugreport #14724. + */ + if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) { + if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) { + TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n"); + gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE; + gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE; + } + } + + /* Find out if PBOs work as they are supposed to */ + test_pbo_functionality(gl_info); + + /* Fixup the driver version */ + for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) { + if(gl_info->gl_vendor == driver_version_table[i].vendor && + gl_info->gl_card == driver_version_table[i].card) { + TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card); + + gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi, + driver_version_table[i].lopart_lo); + gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi, + driver_version_table[i].hipart_lo); + break; } } } -#define PUSH1(att) attribs[nAttribs++] = (att); +static void WINE_GLAPI invalid_func(void *data) { + ERR("Invalid vertex attribute function called\n"); + DebugBreak(); +} + #define GLINFO_LOCATION (Adapters[0].gl_info) + +/* Helper functions for providing vertex data to opengl. The arrays are initialized based on + * the extension detection and are used in drawStridedSlow + */ +static void WINE_GLAPI position_d3dcolor(void *data) { + DWORD pos = *((DWORD *) data); + + FIXME("Add a test for fixed function position from d3dcolor type\n"); + glVertex4s(D3DCOLOR_B_R(pos), + D3DCOLOR_B_G(pos), + D3DCOLOR_B_B(pos), + D3DCOLOR_B_A(pos)); +} +static void WINE_GLAPI position_float4(void *data) { + GLfloat *pos = (float *) data; + + if (pos[3] < eps && pos[3] > -eps) + glVertex3fv(pos); + else { + float w = 1.0 / pos[3]; + + glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w); + } +} + +static void WINE_GLAPI diffuse_d3dcolor(void *data) { + DWORD diffuseColor = *((DWORD *) data); + + glColor4ub(D3DCOLOR_B_R(diffuseColor), + D3DCOLOR_B_G(diffuseColor), + D3DCOLOR_B_B(diffuseColor), + D3DCOLOR_B_A(diffuseColor)); +} + +static void WINE_GLAPI specular_d3dcolor(void *data) { + DWORD specularColor = *((DWORD *) data); + + GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor), + D3DCOLOR_B_G(specularColor), + D3DCOLOR_B_B(specularColor)); +} +static void WINE_GLAPI warn_no_specular_func(void *data) { + WARN("GL_EXT_secondary_color not supported\n"); +} + +void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) { + position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv; + position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4; + position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor; + position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv; + position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func; + position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func; + + diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv; + diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv; + diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor; + diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv; + diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv; + diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv; + diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func; + diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func; + + /* No 4 component entry points here */ + specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func; + if(GL_SUPPORT(EXT_SECONDARY_COLOR)) { + specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT); + } else { + specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func; + } + specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func; + if(GL_SUPPORT(EXT_SECONDARY_COLOR)) { + specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor; + } else { + specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) warn_no_specular_func; + } + specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func; + specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func; + + /* Only 3 component entry points here. Test how others behave. Float4 normals are used + * by one of our tests, trying to pass it to the pixel shader, which fails on Windows. + */ + normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv; + normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */ + normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func; + normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func; +} + +#define PUSH1(att) attribs[nAttribs++] = (att); BOOL InitAdapters(void) { - static HMODULE mod_gl; + static HMODULE mod_gl, mod_win32gl; BOOL ret; int ps_selected_mode, vs_selected_mode; /* No need to hold any lock. The calling library makes sure only one thread calls * wined3d simultaneously */ - if(numAdapters > 0) return TRUE; + if(numAdapters > 0) return Adapters[0].opengl; TRACE("Initializing adapters\n"); @@ -2855,12 +4120,18 @@ BOOL InitAdapters(void) { mod_gl = LoadLibraryA("opengl32.dll"); if(!mod_gl) { ERR("Can't load opengl32.dll!\n"); - return FALSE; + goto nogl_adapter; } + mod_win32gl = mod_gl; #else #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn); /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */ - mod_gl = GetModuleHandleA("opengl32.dll"); + mod_gl = GetModuleHandleA("gdi32.dll"); + mod_win32gl = LoadLibraryA("opengl32.dll"); + if(!mod_win32gl) { + ERR("Can't load opengl32.dll!\n"); + goto nogl_adapter; + } #endif } @@ -2871,57 +4142,61 @@ BOOL InitAdapters(void) { if(!pwglGetProcAddress) { ERR("Unable to load wglGetProcAddress!\n"); - return FALSE; + goto nogl_adapter; } /* Dynamically load all GL core functions */ GL_FUNCS_GEN; #undef USE_GL_FUNC + /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl + * otherwise because we have to use winex11.drv's override + */ + glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish"); + glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush"); + /* For now only one default adapter */ { int iPixelFormat; - int attribs[8]; - int values[8]; + int attribs[10]; + int values[10]; int nAttribs = 0; int res; + int i; WineD3D_PixelFormat *cfgs; int attribute; DISPLAY_DEVICEW DisplayDevice; HDC hdc; TRACE("Initializing default adapter\n"); + Adapters[0].num = 0; Adapters[0].monitorPoint.x = -1; Adapters[0].monitorPoint.y = -1; if (!WineD3D_CreateFakeGLContext()) { ERR("Failed to get a gl context for default adapter\n"); - HeapFree(GetProcessHeap(), 0, Adapters); WineD3D_ReleaseFakeGLContext(); - return FALSE; + goto nogl_adapter; } ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info); if(!ret) { ERR("Failed to initialize gl caps for default adapter\n"); - HeapFree(GetProcessHeap(), 0, Adapters); WineD3D_ReleaseFakeGLContext(); - return FALSE; + goto nogl_adapter; } ret = initPixelFormats(&Adapters[0].gl_info); if(!ret) { ERR("Failed to init gl formats\n"); - HeapFree(GetProcessHeap(), 0, Adapters); WineD3D_ReleaseFakeGLContext(); - return FALSE; + goto nogl_adapter; } hdc = pwglGetCurrentDC(); if(!hdc) { ERR("Failed to get gl HDC\n"); - HeapFree(GetProcessHeap(), 0, Adapters); WineD3D_ReleaseFakeGLContext(); - return FALSE; + goto nogl_adapter; } Adapters[0].driver = "Display"; @@ -2952,6 +4227,10 @@ BOOL InitAdapters(void) { PUSH1(WGL_ALPHA_BITS_ARB) PUSH1(WGL_DEPTH_BITS_ARB) PUSH1(WGL_STENCIL_BITS_ARB) + PUSH1(WGL_DRAW_TO_WINDOW_ARB) + PUSH1(WGL_PIXEL_TYPE_ARB) + PUSH1(WGL_DOUBLE_BUFFER_ARB) + PUSH1(WGL_AUX_BUFFERS_ARB) for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) { res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values)); @@ -2967,22 +4246,88 @@ BOOL InitAdapters(void) { cfgs->alphaSize = values[3]; cfgs->depthSize = values[4]; cfgs->stencilSize = values[5]; + cfgs->windowDrawable = values[6]; + cfgs->iPixelType = values[7]; + cfgs->doubleBuffer = values[8]; + cfgs->auxBuffers = values[9]; - TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize); + cfgs->pbufferDrawable = FALSE; + /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */ + if(GL_SUPPORT(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_SUPPORT(ARB_MULTISAMPLE)) { + int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB}; + int value[2]; + if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) { + /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported. + * value[1] = number of multi sample buffers*/ + if(value[0]) + cfgs->numSamples = value[1]; + } + } + + 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); cfgs++; } - WineD3D_ReleaseFakeGLContext(); + + /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't + * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware + * but just fake it using D24(X8?) which is fine. D3D also allows that. + * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions + * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the + * driver is allowed to consume more bits EXCEPT for stencil bits. + * + * Mark an adapter with this broken stencil behavior. + */ + Adapters[0].brokenStencil = TRUE; + for(i=0, cfgs=Adapters[0].cfgs; iadapter->gl_info #include - -#if 0 /* TODO */ -extern IWineD3DVertexShaderImpl* VertexShaders[64]; -extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64]; -extern IWineD3DPixelShaderImpl* PixelShaders[64]; - -#undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */ -#endif +#include /* Issues the glBegin call for gl given the primitive type and count */ static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType, @@ -133,7 +126,7 @@ static BOOL fixed_get_input( else if (usage == WINED3DDECLUSAGE_SAMPLE && usage_idx == 0) *regnum = 14 + WINED3DDP_MAXTEXCOORD; - if (*regnum < 0) { + if (*regnum == -1) { FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n", debug_d3ddeclusage(usage), usage_idx); return FALSE; @@ -155,7 +148,6 @@ void primitiveDeclarationConvertToStridedData( int i; WINED3DVERTEXELEMENT *element; DWORD stride; - int reg; DWORD numPreloadStreams = This->stateBlock->streamIsUP ? 0 : vertexDeclaration->num_streams; DWORD *streams = vertexDeclaration->streams; @@ -197,7 +189,7 @@ void primitiveDeclarationConvertToStridedData( WARN("loadBaseVertexIndex is < 0 (%d), not using vbos\n", This->stateBlock->loadBaseVertexIndex); streamVBO = 0; data = ((IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory; - if(data + This->stateBlock->loadBaseVertexIndex * stride < 0) { + if((UINT_PTR)data < -This->stateBlock->loadBaseVertexIndex * stride) { FIXME("System memory vertex data load offset is negative!\n"); } } @@ -207,13 +199,16 @@ void primitiveDeclarationConvertToStridedData( else if(*fixup && !useVertexShaderFunction && (element->Usage == WINED3DDECLUSAGE_COLOR || element->Usage == WINED3DDECLUSAGE_POSITIONT)) { - /* This may be bad with the fixed function pipeline */ - FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n"); + static BOOL warned = FALSE; + if(!warned) { + /* This may be bad with the fixed function pipeline */ + FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n"); + warned = TRUE; + } } } } data += element->Offset; - reg = element->Reg; TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex); @@ -273,12 +268,9 @@ static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum #endif } else { - - /* Note first is now zero as we shuffled along earlier */ - TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices); + TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, glPrimitiveType, startVertex, numberOfVertices); glDrawArrays(glPrimitiveType, startVertex, numberOfVertices); checkGLcall("glDrawArrays"); - } return; @@ -297,8 +289,6 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData const WORD *pIdxBufS = NULL; const DWORD *pIdxBufL = NULL; LONG vx_index; - float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */ - float rhw = 0.0f; /* rhw */ DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */ DWORD specularColor = 0; /* Specular Color */ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; @@ -348,6 +338,32 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData position = sd->u.s.position.lpData + streamOffset[sd->u.s.position.streamNo]; } + /* The texture coordinate types are not so easy to map into a common function signature - we're + * not using the vector functions here + */ + if(FIXME_ON(d3d_draw)) { + for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) { + DWORD type = sd->u.s.texCoords[textureNo].dwType; + if (sd->u.s.texCoords[textureNo].lpData && + type != WINED3DDECLTYPE_FLOAT1 && + type != WINED3DDECLTYPE_FLOAT2 && + type != WINED3DDECLTYPE_FLOAT3 && + type != WINED3DDECLTYPE_FLOAT4) { + FIXME("Implement fixed function texture coordinates from %s\n", debug_d3ddecltype(type)); + } + } + if(specular && This->stateBlock->renderState[WINED3DRS_FOGENABLE] && + (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position_transformed )&& + This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { + if(GL_SUPPORT(EXT_FOG_COORD) && sd->u.s.specular.dwType != WINED3DDECLTYPE_D3DCOLOR) { + FIXME("Implement fog coordinates from %s\n", debug_d3ddecltype(sd->u.s.specular.dwType)); + } + } + if(This->activeContext->num_untracked_materials && sd->u.s.diffuse.dwType != WINED3DDECLTYPE_D3DCOLOR) { + FIXME("Implement diffuse color tracking from %s\n", debug_d3ddecltype(sd->u.s.diffuse.dwType)); + } + } + /* Start drawing in GL */ VTRACE(("glBegin(%x)\n", glPrimType)); glBegin(glPrimType); @@ -481,22 +497,13 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData /* Diffuse -------------------------------- */ if (diffuse) { DWORD *ptrToCoords = (DWORD *)(diffuse + (SkipnStrides * sd->u.s.diffuse.dwStride)); - diffuseColor = ptrToCoords[0]; - VTRACE(("diffuseColor=%lx\n", diffuseColor)); - - glColor4ub(D3DCOLOR_B_R(diffuseColor), - D3DCOLOR_B_G(diffuseColor), - D3DCOLOR_B_B(diffuseColor), - D3DCOLOR_B_A(diffuseColor)); - VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n", - D3DCOLOR_B_R(diffuseColor), - D3DCOLOR_B_G(diffuseColor), - D3DCOLOR_B_B(diffuseColor), - D3DCOLOR_B_A(diffuseColor))); + diffuse_funcs[sd->u.s.diffuse.dwType]((void *) ptrToCoords); if(This->activeContext->num_untracked_materials) { unsigned char i; float color[4]; + + diffuseColor = ptrToCoords[0]; color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0; color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0; color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0; @@ -511,14 +518,13 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData /* Specular ------------------------------- */ if (specular) { DWORD *ptrToCoords = (DWORD *)(specular + (SkipnStrides * sd->u.s.specular.dwStride)); - specularColor = ptrToCoords[0]; - VTRACE(("specularColor=%lx\n", specularColor)); /* special case where the fog density is stored in the specular alpha channel */ if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&& This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { if(GL_SUPPORT(EXT_FOG_COORD)) { + specularColor = ptrToCoords[0]; GL_EXTCALL(glFogCoordfEXT(specularColor >> 24)); } else { static BOOL warned = FALSE; @@ -530,52 +536,19 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData } } - VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n", - D3DCOLOR_B_R(specularColor), - D3DCOLOR_B_G(specularColor), - D3DCOLOR_B_B(specularColor))); - if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { - GL_EXTCALL(glSecondaryColor3ubEXT)( - D3DCOLOR_B_R(specularColor), - D3DCOLOR_B_G(specularColor), - D3DCOLOR_B_B(specularColor)); - } else { - /* Do not worry if specular colour missing and disable request */ - VTRACE(("Specular color extensions not supplied\n")); - } + specular_funcs[sd->u.s.specular.dwType]((void *) ptrToCoords); } /* Normal -------------------------------- */ if (normal != NULL) { float *ptrToCoords = (float *)(normal + (SkipnStrides * sd->u.s.normal.dwStride)); - - VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", ptrToCoords[0], ptrToCoords[1], ptrToCoords[2])); - glNormal3f(ptrToCoords[0], ptrToCoords[1], ptrToCoords[2]); + normal_funcs[sd->u.s.normal.dwType](ptrToCoords); } /* Position -------------------------------- */ if (position) { float *ptrToCoords = (float *)(position + (SkipnStrides * sd->u.s.position.dwStride)); - x = ptrToCoords[0]; - y = ptrToCoords[1]; - z = ptrToCoords[2]; - rhw = 1.0; - VTRACE(("x,y,z=%f,%f,%f\n", x,y,z)); - - /* RHW follows, only if transformed, ie 4 floats were provided */ - if (sd->u.s.position_transformed) { - rhw = ptrToCoords[3]; - VTRACE(("rhw=%f\n", rhw)); - } - - if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) { - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z)); - glVertex3f(x, y, z); - } else { - GLfloat w = 1.0 / rhw; - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw)); - glVertex4f(x*w, y*w, z*w, w); - } + position_funcs[sd->u.s.position.dwType](ptrToCoords); } /* For non indexed mode, step onto next parts */ @@ -588,11 +561,158 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData checkGLcall("glEnd and previous calls"); } -static void depth_blt(IWineD3DDevice *iface, GLuint texture) { +static inline void send_attribute(IWineD3DDeviceImpl *This, const DWORD type, const UINT index, const void *ptr) { + switch(type) { + case WINED3DDECLTYPE_FLOAT1: + GL_EXTCALL(glVertexAttrib1fvARB(index, (float *) ptr)); + break; + case WINED3DDECLTYPE_FLOAT2: + GL_EXTCALL(glVertexAttrib2fvARB(index, (float *) ptr)); + break; + case WINED3DDECLTYPE_FLOAT3: + GL_EXTCALL(glVertexAttrib3fvARB(index, (float *) ptr)); + break; + case WINED3DDECLTYPE_FLOAT4: + GL_EXTCALL(glVertexAttrib4fvARB(index, (float *) ptr)); + break; + + case WINED3DDECLTYPE_UBYTE4: + GL_EXTCALL(glVertexAttrib4ubvARB(index, ptr)); + break; + case WINED3DDECLTYPE_UBYTE4N: + case WINED3DDECLTYPE_D3DCOLOR: + GL_EXTCALL(glVertexAttrib4NubvARB(index, ptr)); + break; + + case WINED3DDECLTYPE_SHORT2: + GL_EXTCALL(glVertexAttrib4svARB(index, (GLshort *) ptr)); + break; + case WINED3DDECLTYPE_SHORT4: + GL_EXTCALL(glVertexAttrib4svARB(index, (GLshort *) ptr)); + break; + + case WINED3DDECLTYPE_SHORT2N: + { + GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4NsvARB(index, s)); + break; + } + case WINED3DDECLTYPE_USHORT2N: + { + GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4NusvARB(index, s)); + break; + } + case WINED3DDECLTYPE_SHORT4N: + GL_EXTCALL(glVertexAttrib4NsvARB(index, (GLshort *) ptr)); + break; + case WINED3DDECLTYPE_USHORT4N: + GL_EXTCALL(glVertexAttrib4NusvARB(index, (GLushort *) ptr)); + break; + + case WINED3DDECLTYPE_UDEC3: + FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n"); + /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */ + break; + case WINED3DDECLTYPE_DEC3N: + FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n"); + /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */ + break; + + case WINED3DDECLTYPE_FLOAT16_2: + /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4 + * byte float according to the IEEE standard + */ + if (GL_SUPPORT(NV_HALF_FLOAT)) { + GL_EXTCALL(glVertexAttrib2hvNV(index, (GLhalfNV *)ptr)); + } else { + float x = float_16_to_32(((unsigned short *) ptr) + 0); + float y = float_16_to_32(((unsigned short *) ptr) + 1); + GL_EXTCALL(glVertexAttrib2fARB(index, x, y)); + } + break; + case WINED3DDECLTYPE_FLOAT16_4: + if (GL_SUPPORT(NV_HALF_FLOAT)) { + GL_EXTCALL(glVertexAttrib4hvNV(index, (GLhalfNV *)ptr)); + } else { + float x = float_16_to_32(((unsigned short *) ptr) + 0); + float y = float_16_to_32(((unsigned short *) ptr) + 1); + float z = float_16_to_32(((unsigned short *) ptr) + 2); + float w = float_16_to_32(((unsigned short *) ptr) + 3); + GL_EXTCALL(glVertexAttrib4fARB(index, x, y, z, w)); + } + break; + + case WINED3DDECLTYPE_UNUSED: + default: + ERR("Unexpected attribute declaration: %d\n", type); + break; + } +} + +static void drawStridedSlowVs(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, UINT numberOfVertices, + GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, + ULONG startVertex) { + + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + long SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex; + const WORD *pIdxBufS = NULL; + const DWORD *pIdxBufL = NULL; + LONG vx_index; + int i; + IWineD3DStateBlockImpl *stateblock = This->stateBlock; + 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 = ((IWineD3DIndexBufferImpl *) stateblock->pIndexData)->resource.allocatedMemory; + } + + if (idxSize == 2) pIdxBufS = (const WORD *) idxData; + else pIdxBufL = (const DWORD *) idxData; + } + + /* 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])); + SkipnStrides = pIdxBufS[startIdx + vx_index] + stateblock->loadBaseVertexIndex; + } else { + VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index])); + SkipnStrides = pIdxBufL[startIdx + vx_index] + stateblock->loadBaseVertexIndex; + } + } + + for(i = MAX_ATTRIBS - 1; i >= 0; i--) { + if(!sd->u.input[i].lpData) continue; + + ptr = sd->u.input[i].lpData + + sd->u.input[i].dwStride * SkipnStrides + + stateblock->streamOffset[sd->u.input[i].streamNo]; + + send_attribute(This, sd->u.input[i].dwType, i, ptr); + } + SkipnStrides++; + } + + glEnd(); +} + +void depth_blt(IWineD3DDevice *iface, GLuint texture, GLsizei w, GLsizei h) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLint old_binding = 0; - glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); @@ -601,7 +721,9 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); glBlendFunc(GL_ZERO, GL_ONE); + glViewport(0, 0, w, h); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); @@ -621,68 +743,7 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { glPopAttrib(); - /* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders, - * and this seems easier and more efficient than providing the shader backend with a private - * storage to read and restore the old shader settings - */ - This->shader_backend->shader_select(iface, use_ps(This), use_vs(This)); -} - -static void depth_copy(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer; - - /* Only copy the depth buffer if there is one. */ - if (!depth_stencil) return; - - /* TODO: Make this work for modes other than FBO */ - if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return; - - if (depth_stencil->current_renderbuffer) { - FIXME("Not supported with fixed up depth stencil\n"); - return; - } - - if (This->render_offscreen) { - static GLuint tmp_texture = 0; - GLint old_binding = 0; - - TRACE("Copying onscreen depth buffer to offscreen surface\n"); - - if (!tmp_texture) { - glGenTextures(1, &tmp_texture); - } - - /* Note that we use depth_blt here as well, rather than glCopyTexImage2D - * directly on the FBO texture. That's because we need to flip. */ - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); - glBindTexture(GL_TEXTURE_2D, tmp_texture); - glCopyTexImage2D(depth_stencil->glDescription.target, - depth_stencil->glDescription.level, - depth_stencil->glDescription.glFormatInternal, - 0, - 0, - depth_stencil->currentDesc.Width, - depth_stencil->currentDesc.Height, - 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); - glBindTexture(GL_TEXTURE_2D, old_binding); - - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo)); - checkGLcall("glBindFramebuffer()"); - depth_blt(iface, tmp_texture); - checkGLcall("depth_blt"); - } else { - TRACE("Copying offscreen surface to onscreen depth buffer\n"); - - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - checkGLcall("glBindFramebuffer()"); - depth_blt(iface, depth_stencil->glDescription.textureName); - checkGLcall("depth_blt"); - } + This->shader_backend->shader_deselect_depth_blt(iface); } static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, UINT numberOfVertices, @@ -710,15 +771,15 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVerte /* First, figure out how many instances we have to draw */ for(i = 0; i < MAX_STREAMS; i++) { - /* Look at all non-instanced streams */ - if(!(stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INSTANCEDATA) && - stateblock->streamSource[i]) { - int inst = stateblock->streamFreq[i]; - - if(numInstances && inst != numInstances) { - ERR("Two streams specify a different number of instances. Got %d, new is %d\n", numInstances, inst); + /* Look at the streams and take the first one which matches */ + if(((stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INSTANCEDATA) || (stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INDEXEDDATA)) && stateblock->streamSource[i]) { + /* D3D9 could set streamFreq 0 with (INSTANCEDATA or INDEXEDDATA) and then it is handled as 1. See d3d9/tests/visual.c-> stream_test() */ + if(stateblock->streamFreq[i] == 0){ + numInstances = 1; + } else { + numInstances = stateblock->streamFreq[i]; /* use the specified number of instances from the first matched stream. See d3d9/tests/visual.c-> stream_test() */ } - numInstances = inst; + break; /* break, because only the first suitable value is interesting */ } } @@ -741,86 +802,7 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVerte ptr += (long) vb->resource.allocatedMemory; } - switch(sd->u.input[instancedData[j]].dwType) { - case WINED3DDECLTYPE_FLOAT1: - GL_EXTCALL(glVertexAttrib1fvARB(instancedData[j], (float *) ptr)); - break; - case WINED3DDECLTYPE_FLOAT2: - GL_EXTCALL(glVertexAttrib2fvARB(instancedData[j], (float *) ptr)); - break; - case WINED3DDECLTYPE_FLOAT3: - GL_EXTCALL(glVertexAttrib3fvARB(instancedData[j], (float *) ptr)); - break; - case WINED3DDECLTYPE_FLOAT4: - GL_EXTCALL(glVertexAttrib4fvARB(instancedData[j], (float *) ptr)); - break; - - case WINED3DDECLTYPE_UBYTE4: - GL_EXTCALL(glVertexAttrib4ubvARB(instancedData[j], ptr)); - break; - case WINED3DDECLTYPE_UBYTE4N: - case WINED3DDECLTYPE_D3DCOLOR: - GL_EXTCALL(glVertexAttrib4NubvARB(instancedData[j], ptr)); - break; - - case WINED3DDECLTYPE_SHORT2: - GL_EXTCALL(glVertexAttrib4svARB(instancedData[j], (GLshort *) ptr)); - break; - case WINED3DDECLTYPE_SHORT4: - GL_EXTCALL(glVertexAttrib4svARB(instancedData[j], (GLshort *) ptr)); - break; - - case WINED3DDECLTYPE_SHORT2N: - { - GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1}; - GL_EXTCALL(glVertexAttrib4NsvARB(instancedData[j], s)); - break; - } - case WINED3DDECLTYPE_USHORT2N: - { - GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1}; - GL_EXTCALL(glVertexAttrib4NusvARB(instancedData[j], s)); - break; - } - case WINED3DDECLTYPE_SHORT4N: - GL_EXTCALL(glVertexAttrib4NsvARB(instancedData[j], (GLshort *) ptr)); - break; - case WINED3DDECLTYPE_USHORT4N: - GL_EXTCALL(glVertexAttrib4NusvARB(instancedData[j], (GLushort *) ptr)); - break; - - case WINED3DDECLTYPE_UDEC3: - FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n"); - /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */ - break; - case WINED3DDECLTYPE_DEC3N: - FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n"); - /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */ - break; - - case WINED3DDECLTYPE_FLOAT16_2: - /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4 - * byte float according to the IEEE standard - */ - if (GL_SUPPORT(NV_HALF_FLOAT)) { - GL_EXTCALL(glVertexAttrib2hvNV(instancedData[j], (GLhalfNV *)ptr)); - } else { - FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n"); - } - break; - case WINED3DDECLTYPE_FLOAT16_4: - if (GL_SUPPORT(NV_HALF_FLOAT)) { - GL_EXTCALL(glVertexAttrib4hvNV(instancedData[j], (GLhalfNV *)ptr)); - } else { - FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n"); - } - break; - - case WINED3DDECLTYPE_UNUSED: - default: - ERR("Unexpected declaration in instanced attributes\n"); - break; - } + send_attribute(This, sd->u.input[instancedData[j]].dwType, instancedData[j], ptr); } glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, @@ -930,73 +912,35 @@ void drawPrimitive(IWineD3DDevice *iface, int minIndex) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSwapChain *swapchain; - IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *target; int i; - /* Signals other modules that a drawing is in progress and the stateblock finalized */ - This->isInDraw = TRUE; + if (NumPrimitives == 0) return; /* Invalidate the back buffer memory so LockRect will read it the next time */ for(i = 0; i < GL_LIMITS(buffers); i++) { target = (IWineD3DSurfaceImpl *) This->render_targets[i]; - - /* TODO: Only do all that if we're going to change anything - * Texture container dirtification does not work quite right yet - */ - if(target /*&& target->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)*/) { - swapchain = NULL; - texture = NULL; - - if(i == 0) { - IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DSwapChain, (void **)&swapchain); - - /* Need the surface in the drawable! */ - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - - /* TODO: Move fbo logic to ModifyLocation */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); - if(swapchain) { - /* Onscreen target. Invalidate system memory copy and texture copy */ - IWineD3DSwapChain_Release(swapchain); - } else if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) { - /* Non-FBO target: Invalidate system copy, texture copy and dirtify the container */ - /* TODO: Move container dirtification to ModifyLocation */ - IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DBaseTexture, (void **)&texture); - - if(texture) { - IWineD3DBaseTexture_SetDirty(texture, TRUE); - IWineD3DTexture_Release(texture); - } - } else { - /* FBO offscreen target. Texture == Drawable */ - target->Flags |= SFLAG_INTEXTURE; - } - } else { - /* Must be an fbo render target */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); - target->Flags |= SFLAG_INTEXTURE; - } + if (target) { + IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); } } - /* Ok, we will be updating the screen from here onwards so grab the lock */ - - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - ENTER_GL(); - apply_fbo_state(iface); - LEAVE_GL(); - } + /* Signals other modules that a drawing is in progress and the stateblock finalized */ + This->isInDraw = TRUE; ActivateContext(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); - ENTER_GL(); - if (This->depth_copy_state == WINED3D_DCS_COPY) { - depth_copy(iface); + if (This->stencilBufferTarget) { + /* Note that this depends on the ActivateContext call above to set + * This->render_offscreen properly */ + DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + surface_load_ds_location(This->stencilBufferTarget, location); + surface_modify_ds_location(This->stencilBufferTarget, location); } - This->depth_copy_state = WINED3D_DCS_INITIAL; + /* Ok, we will be updating the screen from here onwards so grab the lock */ + ENTER_GL(); { GLenum glPrimType; BOOL emulation = FALSE; @@ -1011,14 +955,26 @@ void drawPrimitive(IWineD3DDevice *iface, if(!use_vs(This)) { if(!This->strided_streams.u.s.position_transformed && This->activeContext->num_untracked_materials && This->stateBlock->renderState[WINED3DRS_LIGHTING]) { - FIXME("Using software emulation because not all material properties could be tracked\n"); + static BOOL first = TRUE; + if(first) { + FIXME("Using software emulation because not all material properties could be tracked\n"); + first = FALSE; + } else { + TRACE("Using software emulation because not all material properties could be tracked\n"); + } emulation = TRUE; } else if(This->activeContext->fog_coord && This->stateBlock->renderState[WINED3DRS_FOGENABLE]) { /* Either write a pipeline replacement shader or convert the specular alpha from unsigned byte * to a float in the vertex buffer */ - FIXME("Using software emulation because manual fog coordinates are provided\n"); + static BOOL first = TRUE; + if(first) { + FIXME("Using software emulation because manual fog coordinates are provided\n"); + first = FALSE; + } else { + TRACE("Using software emulation because manual fog coordinates are provided\n"); + } emulation = TRUE; } @@ -1031,20 +987,31 @@ void drawPrimitive(IWineD3DDevice *iface, if (This->useDrawStridedSlow || emulation) { /* Immediate mode drawing */ - drawStridedSlow(iface, strided, calculatedNumberOfindices, - glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex); + if(use_vs(This)) { + static BOOL first = TRUE; + if(first) { + FIXME("Using immediate mode with vertex shaders for half float emulation\n"); + first = FALSE; + } else { + TRACE("Using immediate mode with vertex shaders for half float emulation\n"); + } + drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType, + idxData, idxSize, minIndex, StartIdx, StartVertexIndex); + } else { + drawStridedSlow(iface, strided, calculatedNumberOfindices, + glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex); + } } else if(This->instancedDraw) { /* Instancing emulation with mixing immediate mode and arrays */ drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex); } else { - /* Simple array draw call */ drawStridedFast(iface, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex); } } - /* Finshed updating the screen, restore lock */ + /* Finished updating the screen, restore lock */ LEAVE_GL(); TRACE("Done all gl drawing\n"); @@ -1057,11 +1024,11 @@ void drawPrimitive(IWineD3DDevice *iface, if (primCounter >= 0) { WINED3DLOCKED_RECT r; char buffer[80]; - IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY); - sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter); + IWineD3DSurface_LockRect(This->render_targets[0], &r, NULL, WINED3DLOCK_READONLY); + sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter); TRACE("Saving screenshot %s\n", buffer); - IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer); - IWineD3DSurface_UnlockRect(This->renderTarget); + IWineD3DSurface_SaveSnapshot(This->render_targets[0], buffer); + IWineD3DSurface_UnlockRect(This->render_targets[0]); #ifdef SHOW_TEXTURE_MAKEUP { @@ -1069,7 +1036,7 @@ void drawPrimitive(IWineD3DDevice *iface, int textureNo; for (textureNo = 0; textureNo < MAX_COMBINED_SAMPLERS; ++textureNo) { if (This->stateBlock->textures[textureNo] != NULL) { - sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo); + sprintf(buffer, "/tmp/texture_%p_%ld_%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((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur); @@ -1083,7 +1050,7 @@ void drawPrimitive(IWineD3DDevice *iface, } #endif } - TRACE("drawprim #%d\n", primCounter); + TRACE("drawprim #%ld\n", primCounter); ++primCounter; } #endif @@ -1105,11 +1072,11 @@ static void normalize_normal(float *n) { * * The problem is that OpenGL does not offer a direct way to return the tesselated primitives, * and they can't be sent off for rendering directly either. Tesselating is slow, so we want - * to chache the patches in a vertex buffer. But more importantly, gl can't bind generated + * to cache the patches in a vertex buffer. But more importantly, gl can't bind generated * attributes to numbered shader attributes, so we have to store them and rebind them as needed * in drawprim. * - * To read back, the opengl feedback mode is used. This creates a proplem because we want + * To read back, the opengl feedback mode is used. This creates a problem because we want * untransformed, unlit vertices, but feedback runs everything through transform and lighting. * Thus disable lighting and set identity matrices to get unmodified colors and positions. * To overcome clipping find the biggest x, y and z values of the vertices in the patch and scale @@ -1316,11 +1283,13 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, i = glRenderMode(GL_RENDER); if(i == -1) { + LEAVE_GL(); ERR("Feedback failed. Expected %d elements back\n", buffer_size); Sleep(10000); HeapFree(GetProcessHeap(), 0, feedbuffer); return WINED3DERR_DRIVERINTERNALERROR; } else if(i != buffer_size) { + LEAVE_GL(); ERR("Unexpected amount of elements returned. Expected %d, got %d\n", buffer_size, i); Sleep(10000); HeapFree(GetProcessHeap(), 0, feedbuffer); diff --git a/reactos/dll/directx/wine/wined3d/glsl_shader.c b/reactos/dll/directx/wine/wined3d/glsl_shader.c index d9e525bb5aa..3ce81880d14 100644 --- a/reactos/dll/directx/wine/wined3d/glsl_shader.c +++ b/reactos/dll/directx/wine/wined3d/glsl_shader.c @@ -3,6 +3,7 @@ * * Copyright 2006 Jason Green * Copyright 2006-2007 Henri Verbeet + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,16 +34,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); +WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); #define GLINFO_LOCATION (*gl_info) typedef struct { - char reg_name[50]; + char reg_name[150]; char mask_str[6]; } glsl_dst_param_t; typedef struct { - char reg_name[50]; + char reg_name[150]; char param_str[100]; } glsl_src_param_t; @@ -51,11 +53,59 @@ typedef struct { DWORD coord_mask; } glsl_sample_function_t; +/* GLSL shader private data */ +struct shader_glsl_priv { + struct hash_table_t *glsl_program_lookup; + struct glsl_shader_prog_link *glsl_program; + GLhandleARB depth_blt_glsl_program_id; +}; + +/* Struct to maintain data about a linked GLSL program */ +struct glsl_shader_prog_link { + struct list vshader_entry; + struct list pshader_entry; + GLhandleARB programId; + GLhandleARB *vuniformF_locations; + GLhandleARB *puniformF_locations; + GLhandleARB vuniformI_locations[MAX_CONST_I]; + GLhandleARB puniformI_locations[MAX_CONST_I]; + GLhandleARB posFixup_location; + GLhandleARB bumpenvmat_location[MAX_TEXTURES]; + GLhandleARB luminancescale_location[MAX_TEXTURES]; + GLhandleARB luminanceoffset_location[MAX_TEXTURES]; + GLhandleARB srgb_comparison_location; + GLhandleARB srgb_mul_low_location; + GLhandleARB ycorrection_location; + GLenum vertex_color_clamp; + GLhandleARB vshader; + GLhandleARB pshader; +}; + +typedef struct { + GLhandleARB vshader; + GLhandleARB pshader; +} glsl_program_key_t; + + /** Prints the GLSL info log which will contain error messages if they exist */ -void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) { - +static void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) { int infologLength = 0; char *infoLog; + int i; + BOOL is_spam; + + const char *spam[] = { + "Vertex shader was successfully compiled to run on hardware.\n", /* fglrx */ + "Fragment shader was successfully compiled to run on hardware.\n", /* fglrx */ + "Fragment shader(s) linked, vertex shader(s) linked. \n ", /* fglrx, with \n */ + "Fragment shader(s) linked, vertex shader(s) linked.", /* fglrx, no \n */ + "Vertex shader(s) linked, no fragment shader(s) defined. \n ", /* fglrx, with \n */ + "Vertex shader(s) linked, no fragment shader(s) defined.", /* fglrx, no \n */ + "Fragment shader was successfully compiled to run on hardware.\nWARNING: 0:1: extension 'GL_ARB_draw_buffers' is not supported", + "Fragment shader(s) linked, no vertex shader(s) defined.", /* fglrx, no \n */ + "Fragment shader(s) linked, no vertex shader(s) defined. \n ", /* fglrx, with \n */ + "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported\n" /* MacOS ati */ + }; GL_EXTCALL(glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, @@ -65,9 +115,24 @@ void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) { * that if there are errors. */ if (infologLength > 1) { - infoLog = HeapAlloc(GetProcessHeap(), 0, infologLength); + /* Fglrx doesn't terminate the string properly, but it tells us the proper length. + * So use HEAP_ZERO_MEMORY to avoid uninitialized bytes + */ + infoLog = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, infologLength); GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog)); - FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog)); + is_spam = FALSE; + + for(i = 0; i < sizeof(spam) / sizeof(spam[0]); i++) { + if(strcmp(infoLog, spam[i]) == 0) { + is_spam = TRUE; + break; + } + } + if(is_spam) { + TRACE("Spam received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog)); + } else { + FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog)); + } HeapFree(GetProcessHeap(), 0, infoLog); } } @@ -332,19 +397,21 @@ static void shader_glsl_load_constantsB( /** * Loads the app-supplied constants into the currently set GLSL program. */ -void shader_glsl_load_constants( +static void shader_glsl_load_constants( IWineD3DDevice* device, char usePixelShader, char useVertexShader) { IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv; IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; GLhandleARB *constant_locations; struct list *constant_list; GLhandleARB programId; - struct glsl_shader_prog_link *prog = stateBlock->glsl_program; + struct glsl_shader_prog_link *prog = priv->glsl_program; + unsigned int i; if (!prog) { /* No GLSL program set - nothing to do. */ @@ -403,25 +470,29 @@ void shader_glsl_load_constants( /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. * It can't be 0 for a valid texbem instruction. */ - if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != -1) { - float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; - GL_EXTCALL(glUniformMatrix2fvARB(prog->bumpenvmat_location, 1, 0, data)); + for(i = 0; i < ((IWineD3DPixelShaderImpl *) pshader)->numbumpenvmatconsts; i++) { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pshader; + int stage = ps->luminanceconst[i].texunit; + + float *data = (float *) &stateBlock->textureState[(int) ps->bumpenvmatconst[i].texunit][WINED3DTSS_BUMPENVMAT00]; + GL_EXTCALL(glUniformMatrix2fvARB(prog->bumpenvmat_location[i], 1, 0, data)); checkGLcall("glUniformMatrix2fvARB"); /* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat * is set too, so we can check that in the needsbumpmat check */ - if(((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams != -1) { - int stage = ((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams; + if(ps->baseShader.reg_maps.luminanceparams[stage]) { GLfloat *scale = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; GLfloat *offset = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; - GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location, 1, scale)); + GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location[i], 1, scale)); checkGLcall("glUniform1fvARB"); - GL_EXTCALL(glUniform1fvARB(prog->luminanceoffset_location, 1, offset)); + GL_EXTCALL(glUniform1fvARB(prog->luminanceoffset_location[i], 1, offset)); checkGLcall("glUniform1fvARB"); } - } else if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && + } + + if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { float comparison[4]; float mul_low[4]; @@ -459,7 +530,7 @@ void shader_glsl_load_constants( } /** Generate the variable & register declarations for the GLSL output target */ -void shader_generate_glsl_declarations( +static void shader_generate_glsl_declarations( IWineD3DBaseShader *iface, shader_reg_maps* reg_maps, SHADER_BUFFER* buffer, @@ -478,7 +549,7 @@ void shader_generate_glsl_declarations( /* Prototype the subroutines */ for (i = 0; i < This->baseShader.limits.label; i++) { if (reg_maps->labels[i]) - shader_addline(buffer, "void subroutine%lu();\n", i); + shader_addline(buffer, "void subroutine%u();\n", i); } /* Declare the constants (aka uniforms) */ @@ -514,14 +585,26 @@ void shader_generate_glsl_declarations( } else { IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; - if(reg_maps->bumpmat != -1) { - shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); - if(reg_maps->luminanceparams) { - shader_addline(buffer, "uniform float luminancescale;\n"); - shader_addline(buffer, "uniform float luminanceoffset;\n"); - extra_constants_needed++; + ps_impl->numbumpenvmatconsts = 0; + for(i = 0; i < (sizeof(reg_maps->bumpmat) / sizeof(reg_maps->bumpmat[0])); i++) { + if(!reg_maps->bumpmat[i]) { + continue; } + + ps_impl->bumpenvmatconst[(int) ps_impl->numbumpenvmatconsts].texunit = i; + shader_addline(buffer, "uniform mat2 bumpenvmat%d;\n", i); + + if(reg_maps->luminanceparams) { + ps_impl->luminanceconst[(int) ps_impl->numbumpenvmatconsts].texunit = i; + shader_addline(buffer, "uniform float luminancescale%d;\n", i); + shader_addline(buffer, "uniform float luminanceoffset%d;\n", i); + extra_constants_needed++; + } else { + ps_impl->luminanceconst[(int) ps_impl->numbumpenvmatconsts].texunit = -1; + } + extra_constants_needed++; + ps_impl->numbumpenvmatconsts++; } if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { @@ -573,19 +656,24 @@ void shader_generate_glsl_declarations( switch (stype) { case WINED3DSTT_1D: - shader_addline(buffer, "uniform sampler1D %csampler%lu;\n", prefix, i); + shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i); break; case WINED3DSTT_2D: - shader_addline(buffer, "uniform sampler2D %csampler%lu;\n", prefix, i); + 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: - shader_addline(buffer, "uniform samplerCube %csampler%lu;\n", prefix, i); + shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i); break; case WINED3DSTT_VOLUME: - shader_addline(buffer, "uniform sampler3D %csampler%lu;\n", prefix, i); + shader_addline(buffer, "uniform sampler3D %csampler%u;\n", prefix, i); break; default: - shader_addline(buffer, "uniform unsupported_sampler %csampler%lu;\n", prefix, i); + shader_addline(buffer, "uniform unsupported_sampler %csampler%u;\n", prefix, i); FIXME("Unrecognized sampler type: %#x\n", stype); break; } @@ -601,33 +689,33 @@ void shader_generate_glsl_declarations( /* Declare texture coordinate temporaries and initialize them */ for (i = 0; i < This->baseShader.limits.texcoord; i++) { if (reg_maps->texcoord[i]) - shader_addline(buffer, "vec4 T%lu = gl_TexCoord[%lu];\n", i, i); + shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i); } /* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the * helper function shader that is linked in at link time */ - if(pshader && This->baseShader.hex_version >= WINED3DVS_VERSION(3, 0)) { + if(pshader && This->baseShader.hex_version >= WINED3DPS_VERSION(3, 0)) { if(use_vs(device)) { - shader_addline(buffer, "varying vec4 IN[%lu];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); } else { /* TODO: Write a replacement shader for the fixed function vertex pipeline, so this isn't needed. * For fixed function vertex processing + 3.0 pixel shader we need a separate function in the * pixel shader that reads the fixed function color into the packed input registers. */ - shader_addline(buffer, "vec4 IN[%lu];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(buffer, "vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); } } /* Declare output register temporaries */ if(This->baseShader.limits.packed_output) { - shader_addline(buffer, "vec4 OUT[%lu];\n", This->baseShader.limits.packed_output); + shader_addline(buffer, "vec4 OUT[%u];\n", This->baseShader.limits.packed_output); } /* Declare temporary variables */ for(i = 0; i < This->baseShader.limits.temporary; i++) { if (reg_maps->temporary[i]) - shader_addline(buffer, "vec4 R%lu;\n", i); + shader_addline(buffer, "vec4 R%u;\n", i); } /* Declare attributes */ @@ -646,19 +734,34 @@ void shader_generate_glsl_declarations( shader_addline(buffer, "vec4 tmp0;\n"); shader_addline(buffer, "vec4 tmp1;\n"); - /* Hardcodeable local constants */ + /* Local constants use a different name so they can be loaded once at shader link time + * They can't be hardcoded into the shader text via LC = {x, y, z, w}; because the + * float -> string conversion can cause precision loss. + */ if(!This->baseShader.load_local_constsF) { LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - float *value = (float *) lconst->value; - shader_addline(buffer, "const vec4 LC%u = vec4(%f, %f, %f, %f);\n", lconst->idx, - value[0], value[1], value[2], value[3]); + shader_addline(buffer, "uniform vec4 %cLC%u;\n", prefix, lconst->idx); } } /* Start the main program */ shader_addline(buffer, "void main() {\n"); if(pshader && reg_maps->vpos) { - shader_addline(buffer, "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1) - 0.5;\n"); + /* DirectX apps expect integer values, while OpenGL drivers add approximately 0.5. This causes + * off-by-one problems as spotted by the vPos d3d9 visual test. Unfortunately the ATI cards do + * not add exactly 0.5, but rather something like 0.49999999 or 0.50000001, which still causes + * precision troubles when we just substract 0.5. + * + * To deal with that just floor() the position. This will eliminate the fraction on all cards. + * + * TODO: Test how that behaves with multisampling once we can enable multisampling in winex11. + * + * An advantage of floor is that it works even if the driver doesn't add 1/2. It is somewhat + * questionable if 1.5, 2.5, ... are the proper values to return in gl_FragCoord, even though + * coordinates specify the pixel centers instead of the pixel corners. This code will behave + * correctly on drivers that returns integer values. + */ + shader_addline(buffer, "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n"); } } @@ -749,17 +852,6 @@ static void shader_glsl_gen_modifier ( } } -static BOOL constant_is_local(IWineD3DBaseShaderImpl* This, DWORD reg) { - local_constant* lconst; - - if(This->baseShader.load_local_constsF) return FALSE; - LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - if(lconst->idx == reg) return TRUE; - } - return FALSE; - -} - /** Writes the GLSL variable name that corresponds to the register that the * DX opcode parameter is trying to access */ static void shader_glsl_get_register_name( @@ -779,7 +871,7 @@ static void shader_glsl_get_register_name( WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; char pshader = shader_is_pshader_version(This->baseShader.hex_version); - char tmpStr[50]; + char tmpStr[150]; *is_color = FALSE; @@ -791,6 +883,8 @@ static void shader_glsl_get_register_name( if (pshader) { /* Pixel shaders >= 3.0 */ if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3) { + DWORD in_count = GL_LIMITS(glsl_varyings) / 4; + if (param & WINED3DSHADER_ADDRMODE_RELATIVE) { glsl_src_param_t rel_param; shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param); @@ -799,14 +893,33 @@ static void shader_glsl_get_register_name( * operation there */ if(((IWineD3DPixelShaderImpl *) This)->input_reg_map[reg]) { - sprintf(tmpStr, "IN[%s + %u]", rel_param.param_str, - ((IWineD3DPixelShaderImpl *) This)->input_reg_map[reg]); + if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) { + sprintf(tmpStr, "((%s + %u) > %d ? (%s + %u) > %d ? gl_SecondaryColor : gl_Color : IN[%s + %u])", + rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg], in_count - 1, + rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg], in_count, + rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg]); + } else { + sprintf(tmpStr, "IN[%s + %u]", rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg]); + } } else { - sprintf(tmpStr, "IN[%s]", rel_param.param_str); + if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) { + sprintf(tmpStr, "((%s) > %d ? (%s) > %d ? gl_SecondaryColor : gl_Color : IN[%s])", + rel_param.param_str, in_count - 1, + rel_param.param_str, in_count, + rel_param.param_str); + } else { + sprintf(tmpStr, "IN[%s]", rel_param.param_str); + } } } else { - sprintf(tmpStr, "IN[%u]", - ((IWineD3DPixelShaderImpl *) This)->input_reg_map[reg]); + DWORD idx = ((IWineD3DPixelShaderImpl *) This)->input_reg_map[reg]; + if (idx == in_count) { + sprintf(tmpStr, "gl_Color"); + } else if (idx == in_count + 1) { + sprintf(tmpStr, "gl_SecondaryColor"); + } else { + sprintf(tmpStr, "IN[%u]", idx); + } } } else { if (reg==0) @@ -822,7 +935,7 @@ static void shader_glsl_get_register_name( break; case WINED3DSPR_CONST: { - const char* prefix = pshader? "PC":"VC"; + const char prefix = pshader? 'P':'V'; /* Relative addressing */ if (param & WINED3DSHADER_ADDRMODE_RELATIVE) { @@ -833,23 +946,23 @@ static void shader_glsl_get_register_name( glsl_src_param_t rel_param; shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param); if(reg) { - sprintf(tmpStr, "%s[%s + %u]", prefix, rel_param.param_str, reg); + sprintf(tmpStr, "%cC[%s + %u]", prefix, rel_param.param_str, reg); } else { - sprintf(tmpStr, "%s[%s]", prefix, rel_param.param_str); + sprintf(tmpStr, "%cC[%s]", prefix, rel_param.param_str); } } else { if(reg) { - sprintf(tmpStr, "%s[A0.x + %u]", prefix, reg); + sprintf(tmpStr, "%cC[A0.x + %u]", prefix, reg); } else { - sprintf(tmpStr, "%s[A0.x]", prefix); + sprintf(tmpStr, "%cC[A0.x]", prefix); } } } else { - if(constant_is_local(This, reg)) { - sprintf(tmpStr, "LC%u", reg); + if(shader_constant_is_local(This, reg)) { + sprintf(tmpStr, "%cLC%u", prefix, reg); } else { - sprintf(tmpStr, "%s[%u]", prefix, reg); + sprintf(tmpStr, "%cC[%u]", prefix, reg); } } @@ -956,8 +1069,8 @@ static DWORD shader_glsl_get_write_mask(const DWORD param, char *write_mask) { return mask; } -static size_t shader_glsl_get_write_mask_size(DWORD write_mask) { - size_t size = 0; +static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) { + unsigned int size = 0; if (write_mask & WINED3DSP_WRITEMASK_0) ++size; if (write_mask & WINED3DSP_WRITEMASK_1) ++size; @@ -1081,7 +1194,7 @@ static inline const char* shader_get_comp_op( } } -static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected, glsl_sample_function_t *sample_function) { +static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected, BOOL texrect, glsl_sample_function_t *sample_function) { /* Note that there's no such thing as a projected cube texture. */ switch(sampler_type) { case WINED3DSTT_1D: @@ -1089,7 +1202,11 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected, sample_function->coord_mask = WINED3DSP_WRITEMASK_0; break; case WINED3DSTT_2D: - sample_function->name = projected ? "texture2DProj" : "texture2D"; + if(texrect) { + sample_function->name = projected ? "texture2DRectProj" : "texture2DRect"; + } else { + sample_function->name = projected ? "texture2DProj" : "texture2D"; + } sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; break; case WINED3DSTT_CUBE: @@ -1261,6 +1378,41 @@ static void shader_glsl_color_correction(SHADER_OPCODE_ARG* arg) { } break; + case WINED3DFMT_ATI2N: + /* GL_ATI_texture_compression_3dc returns the two channels as luminance-alpha, + * which means the first one is replicated across .rgb, and the 2nd one is in + * .a. We need the 2nd in .g + * + * GL_EXT_texture_compression_rgtc returns the values in .rg, however, they + * are swapped compared to d3d. So swap red and green. + */ + mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &dst_param); + mask_size = shader_glsl_get_write_mask_size(mask); + if(GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { + if(mask_size >= 2) { + shader_addline(arg->buffer, "%s.%c%c = %s.%c%c;\n", + dst_param.reg_name, dst_param.mask_str[1], + dst_param.mask_str[2], + dst_param.reg_name, dst_param.mask_str[2], + dst_param.mask_str[1]); + } else { + FIXME("%u components sampled from a converted ATI2N texture\n", mask_size); + } + } else { + if(mask_size == 4) { + /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ + shader_addline(arg->buffer, "%s.%c = %s.%c;\n", + dst_param.reg_name, dst_param.mask_str[2], + dst_param.reg_name, dst_param.mask_str[4]); + } else if(mask_size == 1) { + /* Nothing to do */ + } else { + FIXME("%u components sampled from a converted ATI2N texture\n", mask_size); + /* This is bad: We have .r[gb], but we need .ra */ + } + } + break; + /* stupid compiler */ default: break; @@ -1313,10 +1465,17 @@ void shader_glsl_mov(SHADER_OPCODE_ARG* arg) { * shader versions WINED3DSIO_MOVA is used for this. */ if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1 && !shader_is_pshader_version(shader->baseShader.hex_version) && - shader_get_regtype(arg->dst) == WINED3DSPR_ADDR) || - arg->opcode->opcode == WINED3DSIO_MOVA) { + shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)) { + /* This is a simple floor() */ + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); + if (mask_size > 1) { + shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str); + } else { + shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str); + } + } else if(arg->opcode->opcode == WINED3DSIO_MOVA) { /* We need to *round* to the nearest int here. */ - size_t mask_size = shader_glsl_get_write_mask_size(write_mask); + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); if (mask_size > 1) { shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n", mask_size, src0_param.param_str, mask_size, src0_param.param_str); } else { @@ -1334,7 +1493,7 @@ void shader_glsl_dot(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD dst_write_mask, src_write_mask; - size_t dst_size = 0; + unsigned int dst_size = 0; dst_write_mask = shader_glsl_append_dst(buffer, arg); dst_size = shader_glsl_get_write_mask_size(dst_write_mask); @@ -1379,7 +1538,7 @@ void shader_glsl_pow(SHADER_OPCODE_ARG *arg) { glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD dst_write_mask; - size_t dst_size; + unsigned int dst_size; dst_write_mask = shader_glsl_append_dst(buffer, arg); dst_size = shader_glsl_get_write_mask_size(dst_write_mask); @@ -1401,7 +1560,7 @@ void shader_glsl_log(SHADER_OPCODE_ARG *arg) { SHADER_BUFFER *buffer = arg->buffer; glsl_src_param_t src0_param; DWORD dst_write_mask; - size_t dst_size; + unsigned int dst_size; dst_write_mask = shader_glsl_append_dst(buffer, arg); dst_size = shader_glsl_get_write_mask_size(dst_write_mask); @@ -1488,7 +1647,7 @@ void shader_glsl_expp(SHADER_OPCODE_ARG* arg) { shader_addline(arg->buffer, "tmp0%s);\n", dst_mask); } else { DWORD write_mask; - size_t mask_size; + unsigned int mask_size; write_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); @@ -1505,7 +1664,7 @@ void shader_glsl_expp(SHADER_OPCODE_ARG* arg) { void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src_param; DWORD write_mask; - size_t mask_size; + unsigned int mask_size; write_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); @@ -1522,7 +1681,7 @@ void shader_glsl_rsq(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; glsl_src_param_t src_param; DWORD write_mask; - size_t mask_size; + unsigned int mask_size; write_mask = shader_glsl_append_dst(buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); @@ -1541,7 +1700,7 @@ void shader_glsl_compare(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD write_mask; - size_t mask_size; + unsigned int mask_size; write_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); @@ -1565,7 +1724,7 @@ void shader_glsl_compare(SHADER_OPCODE_ARG* arg) { case WINED3DSIO_SLT: /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed, * to return 0.0 but step returns 1.0 because step is not < x - * An alternative is a bvec compare padded with an unused secound component. + * An alternative is a bvec compare padded with an unused second component. * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same * issue. Playing with not() is not possible either because not() does not accept * a scalar. @@ -1593,55 +1752,66 @@ void shader_glsl_cmp(SHADER_OPCODE_ARG* arg) { char mask_char[6]; BOOL temp_destination = FALSE; - DWORD src0reg = arg->src[0] & WINED3DSP_REGNUM_MASK; - DWORD src1reg = arg->src[1] & WINED3DSP_REGNUM_MASK; - DWORD src2reg = arg->src[2] & WINED3DSP_REGNUM_MASK; - DWORD src0regtype = shader_get_regtype(arg->src[0]); - DWORD src1regtype = shader_get_regtype(arg->src[1]); - DWORD src2regtype = shader_get_regtype(arg->src[2]); - DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK; - DWORD dstregtype = shader_get_regtype(arg->dst); + if(shader_is_scalar(arg->src[0])) { + write_mask = shader_glsl_append_dst(arg->buffer, arg); - /* Cycle through all source0 channels */ - for (i=0; i<4; i++) { - write_mask = 0; - /* Find the destination channels which use the current source0 channel */ - for (j=0; j<4; j++) { - if ( ((arg->src[0] >> (WINED3DSP_SWIZZLE_SHIFT + 2*j)) & 0x3) == i ) { - write_mask |= WINED3DSP_WRITEMASK_0 << j; - cmp_channel = WINED3DSP_WRITEMASK_0 << j; - } - } - - /* Splitting the cmp instruction up in multiple lines imposes a problem: - * The first lines may overwrite source parameters of the following lines. - * Deal with that by using a temporary destination register if needed - */ - if((src0reg == dstreg && src0regtype == dstregtype) || - (src1reg == dstreg && src1regtype == dstregtype) || - (src2reg == dstreg && src2regtype == dstregtype)) { - - write_mask = shader_glsl_get_write_mask(arg->dst & (~WINED3DSP_SWIZZLE_MASK | write_mask), mask_char); - if (!write_mask) continue; - shader_addline(arg->buffer, "tmp0%s = (", mask_char); - temp_destination = TRUE; - } else { - write_mask = shader_glsl_append_dst_ext(arg->buffer, arg, arg->dst & (~WINED3DSP_SWIZZLE_MASK | write_mask)); - if (!write_mask) continue; - } - - shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], cmp_channel, &src0_param); + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param); shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param); shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param); - shader_addline(arg->buffer, "%s >= 0.0 ? %s : %s);\n", - src0_param.param_str, src1_param.param_str, src2_param.param_str); - } + shader_addline(arg->buffer, "%s >= 0.0 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } else { + DWORD src0reg = arg->src[0] & WINED3DSP_REGNUM_MASK; + DWORD src1reg = arg->src[1] & WINED3DSP_REGNUM_MASK; + DWORD src2reg = arg->src[2] & WINED3DSP_REGNUM_MASK; + DWORD src0regtype = shader_get_regtype(arg->src[0]); + DWORD src1regtype = shader_get_regtype(arg->src[1]); + DWORD src2regtype = shader_get_regtype(arg->src[2]); + DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK; + DWORD dstregtype = shader_get_regtype(arg->dst); - if(temp_destination) { - shader_glsl_get_write_mask(arg->dst, mask_char); - shader_glsl_append_dst_ext(arg->buffer, arg, arg->dst); - shader_addline(arg->buffer, "tmp0%s);\n", mask_char); + /* Cycle through all source0 channels */ + for (i=0; i<4; i++) { + write_mask = 0; + /* Find the destination channels which use the current source0 channel */ + for (j=0; j<4; j++) { + if ( ((arg->src[0] >> (WINED3DSP_SWIZZLE_SHIFT + 2*j)) & 0x3) == i ) { + write_mask |= WINED3DSP_WRITEMASK_0 << j; + cmp_channel = WINED3DSP_WRITEMASK_0 << j; + } + } + + /* Splitting the cmp instruction up in multiple lines imposes a problem: + * The first lines may overwrite source parameters of the following lines. + * Deal with that by using a temporary destination register if needed + */ + if((src0reg == dstreg && src0regtype == dstregtype) || + (src1reg == dstreg && src1regtype == dstregtype) || + (src2reg == dstreg && src2regtype == dstregtype)) { + + write_mask = shader_glsl_get_write_mask(arg->dst & (~WINED3DSP_SWIZZLE_MASK | write_mask), mask_char); + if (!write_mask) continue; + shader_addline(arg->buffer, "tmp0%s = (", mask_char); + temp_destination = TRUE; + } else { + write_mask = shader_glsl_append_dst_ext(arg->buffer, arg, arg->dst & (~WINED3DSP_SWIZZLE_MASK | write_mask)); + if (!write_mask) continue; + } + + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], cmp_channel, &src0_param); + shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param); + shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param); + + shader_addline(arg->buffer, "%s >= 0.0 ? %s : %s);\n", + src0_param.param_str, src1_param.param_str, src2_param.param_str); + } + + if(temp_destination) { + shader_glsl_get_write_mask(arg->dst, mask_char); + shader_glsl_append_dst_ext(arg->buffer, arg, arg->dst); + shader_addline(arg->buffer, "tmp0%s);\n", mask_char); + } } } @@ -2009,12 +2179,12 @@ void shader_glsl_label(SHADER_OPCODE_ARG* arg) { DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK; shader_addline(arg->buffer, "}\n"); - shader_addline(arg->buffer, "void subroutine%lu () {\n", snum); + shader_addline(arg->buffer, "void subroutine%u () {\n", snum); } void shader_glsl_call(SHADER_OPCODE_ARG* arg) { DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK; - shader_addline(arg->buffer, "subroutine%lu();\n", snum); + shader_addline(arg->buffer, "subroutine%u();\n", snum); } void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) { @@ -2022,7 +2192,7 @@ void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) { DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK; shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param); - shader_addline(arg->buffer, "if (%s) subroutine%lu();\n", src1_param.param_str, snum); + shader_addline(arg->buffer, "if (%s) subroutine%u();\n", src1_param.param_str, snum); } /********************************************* @@ -2036,7 +2206,7 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { glsl_sample_function_t sample_function; DWORD sampler_type; DWORD sampler_idx; - BOOL projected; + BOOL projected, texrect = FALSE; DWORD mask = 0; /* All versions have a destination register */ @@ -2086,8 +2256,13 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { } } + if(deviceImpl->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + texrect = TRUE; + } + sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; - shader_glsl_get_sample_function(sampler_type, projected, &sample_function); + shader_glsl_get_sample_function(sampler_type, projected, texrect, &sample_function); mask |= sample_function.coord_mask; if (hex_version < WINED3DPS_VERSION(2,0)) { @@ -2122,19 +2297,24 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { void shader_glsl_texldl(SHADER_OPCODE_ARG* arg) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*)arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; glsl_sample_function_t sample_function; glsl_src_param_t coord_param, lod_param; char dst_swizzle[6]; DWORD sampler_type; DWORD sampler_idx; + BOOL texrect = FALSE; shader_glsl_append_dst(arg->buffer, arg); shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle); sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); - shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &coord_param); + if(deviceImpl->stateBlock->textures[sampler_idx] && + IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) { + texrect = TRUE; + } + shader_glsl_get_sample_function(sampler_type, FALSE, texrect, &sample_function); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &coord_param); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &lod_param); @@ -2175,7 +2355,7 @@ void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) { if (src_mod == WINED3DSPSM_DZ) { glsl_src_param_t div_param; - size_t mask_size = shader_glsl_get_write_mask_size(write_mask); + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &div_param); if (mask_size > 1) { @@ -2185,7 +2365,7 @@ void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) { } } else if (src_mod == WINED3DSPSM_DW) { glsl_src_param_t div_param; - size_t mask_size = shader_glsl_get_write_mask_size(write_mask); + unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &div_param); if (mask_size > 1) { @@ -2216,9 +2396,11 @@ void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) { shader_glsl_get_write_mask(arg->dst, dst_mask); /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one - * scalar, and projected sampling would require 4 + * scalar, and projected sampling would require 4. + * + * It is a dependent read - not valid with conditional NP2 textures */ - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + shader_glsl_get_sample_function(sampler_type, FALSE, FALSE, &sample_function); switch(count_bits(sample_function.coord_mask)) { case 1: @@ -2247,7 +2429,7 @@ void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg) { DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD dst_mask; - size_t mask_size; + unsigned int mask_size; dst_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(dst_mask); @@ -2273,7 +2455,7 @@ void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg) { * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result * >= 1.0 or < 0.0 */ - shader_addline(arg->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n", dst_param.reg_name, dst_param.reg_name, dst_param.reg_name); + shader_addline(arg->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n", dst_param.reg_name, dst_param.reg_name); } /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL: @@ -2354,7 +2536,8 @@ void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) { shader_glsl_append_dst(arg->buffer, arg); shader_glsl_get_write_mask(arg->dst, dst_mask); - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(sampler_type, FALSE, FALSE, &sample_function); /* Sample the texture using the calculated coordinates */ shader_addline(arg->buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask); @@ -2406,7 +2589,8 @@ void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) { shader_glsl_append_dst(buffer, arg); shader_glsl_get_write_mask(arg->dst, dst_mask); - shader_glsl_get_sample_function(stype, FALSE, &sample_function); + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(stype, FALSE, FALSE, &sample_function); /* Sample the texture */ shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask); @@ -2440,7 +2624,8 @@ void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) { shader_glsl_append_dst(buffer, arg); shader_glsl_get_write_mask(arg->dst, dst_mask); - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(sampler_type, FALSE, FALSE, &sample_function); /* Sample the texture using the calculated coordinates */ shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask); @@ -2468,7 +2653,8 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) { flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS]; sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(sampler_type, FALSE, FALSE, &sample_function); mask = sample_function.coord_mask; shader_glsl_get_write_mask(arg->dst, dst_swizzle); @@ -2497,24 +2683,25 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) { if(arg->opcode->opcode == WINED3DSIO_TEXBEML) { glsl_src_param_t luminance_param; shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param); - shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )*(%s * luminancescale + luminanceoffset))%s);\n", - sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, - luminance_param.param_str, dst_swizzle); + shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )*(%s * luminancescale%d + luminanceoffset%d))%s);\n", + sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask, + luminance_param.param_str, sampler_idx, sampler_idx, dst_swizzle); } else { - shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n", - sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle); + shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )%s);\n", + sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask, dst_swizzle); } } void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src0_param, src1_param; + DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src0_param); shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src1_param); shader_glsl_append_dst(arg->buffer, arg); - shader_addline(arg->buffer, "%s + bumpenvmat * %s);\n", - src0_param.param_str, src1_param.param_str); + shader_addline(arg->buffer, "%s + bumpenvmat%d * %s);\n", + src0_param.param_str, sampler_idx, src1_param.param_str); } /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL @@ -2557,7 +2744,8 @@ void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg) { shader_glsl_append_dst(arg->buffer, arg); shader_glsl_get_write_mask(arg->dst, dst_mask); - shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + /* Dependent read, not valid with conditional NP2 */ + shader_glsl_get_sample_function(sampler_type, FALSE, FALSE, &sample_function); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &src0_param); shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n", sample_function.name, sampler_idx, src0_param.param_str, dst_mask); @@ -2591,7 +2779,7 @@ void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg) { glsl_src_param_t src1_param; glsl_src_param_t src2_param; DWORD write_mask; - size_t mask_size; + unsigned int mask_size; write_mask = shader_glsl_append_dst(arg->buffer, arg); mask_size = shader_glsl_get_write_mask_size(write_mask); @@ -2600,10 +2788,14 @@ void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg) { shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], WINED3DSP_WRITEMASK_0, &src2_param); - shader_addline(arg->buffer, "dot(%s, %s) + %s);\n", src0_param.param_str, src1_param.param_str, src2_param.param_str); + if (mask_size > 1) { + shader_addline(arg->buffer, "vec%d(dot(%s, %s) + %s));\n", mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str); + } else { + shader_addline(arg->buffer, "dot(%s, %s) + %s);\n", src0_param.param_str, src1_param.param_str, src2_param.param_str); + } } -void pshader_glsl_input_pack( +static void pshader_glsl_input_pack( SHADER_BUFFER* buffer, semantic* semantics_in, IWineD3DPixelShader *iface) { @@ -2659,35 +2851,33 @@ void pshader_glsl_input_pack( * Vertex Shader Specific Code begins here ********************************************/ -static void add_glsl_program_entry(IWineD3DDeviceImpl *device, struct glsl_shader_prog_link *entry) { +static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) { glsl_program_key_t *key; key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t)); key->vshader = entry->vshader; key->pshader = entry->pshader; - hash_table_put(device->glsl_program_lookup, key, entry); + hash_table_put(priv->glsl_program_lookup, key, entry); } -static struct glsl_shader_prog_link *get_glsl_program_entry(IWineD3DDeviceImpl *device, +static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_priv *priv, GLhandleARB vshader, GLhandleARB pshader) { glsl_program_key_t key; key.vshader = vshader; key.pshader = pshader; - return (struct glsl_shader_prog_link *)hash_table_get(device->glsl_program_lookup, &key); + return (struct glsl_shader_prog_link *)hash_table_get(priv->glsl_program_lookup, &key); } -void delete_glsl_program_entry(IWineD3DDevice *iface, struct glsl_shader_prog_link *entry) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - WineD3D_GL_Info *gl_info = &This->adapter->gl_info; +static void delete_glsl_program_entry(struct shader_glsl_priv *priv, WineD3D_GL_Info *gl_info, struct glsl_shader_prog_link *entry) { glsl_program_key_t *key; key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t)); key->vshader = entry->vshader; key->pshader = entry->pshader; - hash_table_remove(This->glsl_program_lookup, key); + hash_table_remove(priv->glsl_program_lookup, key); GL_EXTCALL(glDeleteObjectARB(entry->programId)); if (entry->vshader) list_remove(&entry->vshader_entry); @@ -2703,20 +2893,40 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema DWORD register_token, register_token_out; DWORD usage, usage_idx, usage_out, usage_idx_out; DWORD *set; + DWORD in_idx; + DWORD in_count = GL_LIMITS(glsl_varyings) / 4; char reg_mask[6], reg_mask_out[6]; + char destination[50]; - set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (GL_LIMITS(glsl_varyings) / 4)); + set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2)); + + if (!semantics_out) { + /* Save gl_FrontColor & gl_FrontSecondaryColor before overwriting them. */ + shader_addline(buffer, "vec4 front_color = gl_FrontColor;\n"); + shader_addline(buffer, "vec4 front_secondary_color = gl_FrontSecondaryColor;\n"); + } for(i = 0; i < MAX_REG_INPUT; i++) { usage_token = semantics_in[i].usage; if (!usage_token) continue; - if(map[i] >= (GL_LIMITS(glsl_varyings) / 4)) { + + in_idx = map[i]; + if (in_idx >= (in_count + 2)) { FIXME("More input varyings declared than supported, expect issues\n"); continue; } else if(map[i] == -1) { /* Declared, but not read register */ continue; } + + if (in_idx == in_count) { + sprintf(destination, "gl_FrontColor"); + } else if (in_idx == in_count + 1) { + sprintf(destination, "gl_FrontSecondaryColor"); + } else { + sprintf(destination, "IN[%u]", in_idx); + } + register_token = semantics_in[i].reg; usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; @@ -2727,34 +2937,34 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema switch(usage) { case WINED3DDECLUSAGE_COLOR: if (usage_idx == 0) - shader_addline(buffer, "IN[%u]%s = gl_FrontColor%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = front_color%s;\n", + destination, reg_mask, reg_mask); else if (usage_idx == 1) - shader_addline(buffer, "IN[%u]%s = gl_FrontSecondaryColor%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = front_secondary_color%s;\n", + destination, reg_mask, reg_mask); else - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); break; case WINED3DDECLUSAGE_TEXCOORD: if (usage_idx < 8) { - shader_addline(buffer, "IN[%u]%s = gl_TexCoord[%u]%s;\n", - map[i], reg_mask, usage_idx, reg_mask); + shader_addline(buffer, "%s%s = gl_TexCoord[%u]%s;\n", + destination, reg_mask, usage_idx, reg_mask); } else { - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); } break; case WINED3DDECLUSAGE_FOG: - shader_addline(buffer, "IN[%u]%s = vec4(gl_FogFragCoord, 0.0, 0.0, 0.0)%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = vec4(gl_FogFragCoord, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); break; default: - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); } } else { BOOL found = FALSE; @@ -2769,14 +2979,14 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema if(usage == usage_out && usage_idx == usage_idx_out) { - shader_addline(buffer, "IN[%u]%s = OUT[%u]%s;\n", - map[i], reg_mask, j, reg_mask); + shader_addline(buffer, "%s%s = OUT[%u]%s;\n", + destination, reg_mask, j, reg_mask); found = TRUE; } } if(!found) { - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - map[i], reg_mask, reg_mask); + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); } } } @@ -2785,7 +2995,7 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema * varyings. It shouldn't result in any real code executed on the GPU, since all read * input varyings are assigned above, if the optimizer works properly. */ - for(i = 0; i < GL_LIMITS(glsl_varyings) / 4; i++) { + for(i = 0; i < in_count + 2; i++) { if(set[i] != WINED3DSP_WRITEMASK_ALL) { unsigned int size = 0; memset(reg_mask, 0, sizeof(reg_mask)); @@ -2805,19 +3015,19 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema reg_mask[size] = 'w'; size++; } - switch(size) { - case 1: - shader_addline(buffer, "IN[%u].%s = 0.0;\n", i, reg_mask); - break; - case 2: - shader_addline(buffer, "IN[%u].%s = vec2(0.0, 0.0);\n", i, reg_mask); - break; - case 3: - shader_addline(buffer, "IN[%u].%s = vec3(0.0, 0.0, 0.0);\n", i, reg_mask); - break; - case 4: - shader_addline(buffer, "IN[%u].%s = vec4(0.0, 0.0, 0.0, 0.0);\n", i, reg_mask); - break; + + if (i == in_count) { + sprintf(destination, "gl_FrontColor"); + } else if (i == in_count + 1) { + sprintf(destination, "gl_FrontSecondaryColor"); + } else { + sprintf(destination, "IN[%u]", i); + } + + if (size == 1) { + shader_addline(buffer, "%s.%s = 0.0;\n", destination, reg_mask); + } else { + shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination, reg_mask, size); } } } @@ -2831,13 +3041,14 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs GLhandleARB ret = 0; IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) vertexshader; IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pixelshader; + IWineD3DDeviceImpl *device; DWORD vs_major = vs ? WINED3DSHADER_VERSION_MAJOR(vs->baseShader.hex_version) : 0; DWORD ps_major = ps ? WINED3DSHADER_VERSION_MAJOR(ps->baseShader.hex_version) : 0; unsigned int i; SHADER_BUFFER buffer; DWORD usage_token; DWORD register_token; - DWORD usage, usage_idx; + DWORD usage, usage_idx, writemask; char reg_mask[6]; semantic *semantics_out, *semantics_in; @@ -2846,9 +3057,26 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs buffer.lineNo = 0; buffer.newline = TRUE; + shader_addline(&buffer, "#version 120\n"); + if(vs_major < 3 && ps_major < 3) { - /* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them */ - shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n"); + /* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them. + * Take care about the texcoord .w fixup though if we're using the fixed function fragment pipeline + */ + device = (IWineD3DDeviceImpl *) vs->baseShader.device; + if((GLINFO_LOCATION).set_texcoord_w && ps_major == 0 && vs_major > 0 && + !device->frag_pipe->ffp_proj_control) { + shader_addline(&buffer, "void order_ps_input() {\n"); + for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) { + if(vs->baseShader.reg_maps.texcoord_mask[i] != 0 && + vs->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) { + shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", i); + } + } + shader_addline(&buffer, "}\n"); + } else { + shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n"); + } } else if(ps_major < 3 && vs_major >= 3) { /* The vertex shader writes to its own varyings, the pixel shader needs them in the builtin ones */ semantics_out = vs->semantics_out; @@ -2861,7 +3089,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT; - shader_glsl_get_write_mask(register_token, reg_mask); + writemask = shader_glsl_get_write_mask(register_token, reg_mask); switch(usage) { case WINED3DDECLUSAGE_COLOR: @@ -2877,8 +3105,13 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs case WINED3DDECLUSAGE_TEXCOORD: if (usage_idx < 8) { + if(!(GLINFO_LOCATION).set_texcoord_w || ps_major > 0) writemask |= WINED3DSP_WRITEMASK_3; + shader_addline(&buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n", - usage_idx, reg_mask, i, reg_mask); + usage_idx, reg_mask, i, reg_mask); + if(!(writemask & WINED3DSP_WRITEMASK_3)) { + shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", usage_idx); + } } break; @@ -2901,7 +3134,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs semantics_in = ps->semantics_in; /* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */ - shader_addline(&buffer, "varying vec4 IN[%lu];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(&buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); shader_addline(&buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT); /* First, sort out position and point size. Those are not passed to the pixel shader */ @@ -2935,7 +3168,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs } else if(ps_major >= 3 && vs_major < 3) { semantics_in = ps->semantics_in; - shader_addline(&buffer, "varying vec4 IN[%lu];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(&buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); shader_addline(&buffer, "void order_ps_input() {\n"); /* The vertex shader wrote to the builtin varyings. There is no need to figure out position and * point size, but we depend on the optimizers kindness to find out that the pixel shader doesn't @@ -2958,6 +3191,21 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs return ret; } +static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, WineD3D_GL_Info *gl_info, GLhandleARB programId, char prefix) { + local_constant* lconst; + GLuint tmp_loc; + float *value; + char glsl_name[8]; + + LIST_FOR_EACH_ENTRY(lconst, &shader->baseShader.constantsF, local_constant, entry) { + value = (float *) lconst->value; + snprintf(glsl_name, sizeof(glsl_name), "%cLC%u", prefix, lconst->idx); + tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, value)); + } + checkGLcall("Hardcoding local constants\n"); +} + /** Sets the GLSL program ID for the given pixel and vertex shader combination. * It sets the programId on the current StateBlock (because it should be called * inside of the DrawPrimitive() part of the render loop). @@ -2968,6 +3216,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs */ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use_vs) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; IWineD3DPixelShader *pshader = This->stateBlock->pixelShader; IWineD3DVertexShader *vshader = This->stateBlock->vertexShader; @@ -2979,9 +3228,9 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use GLhandleARB vshader_id = use_vs ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0; GLhandleARB pshader_id = use_ps ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0; - entry = get_glsl_program_entry(This, vshader_id, pshader_id); + entry = get_glsl_program_entry(priv, vshader_id, pshader_id); if (entry) { - This->stateBlock->glsl_program = entry; + priv->glsl_program = entry; return; } @@ -2995,16 +3244,25 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use entry->vshader = vshader_id; entry->pshader = pshader_id; /* Add the hash table entry */ - add_glsl_program_entry(This, entry); + add_glsl_program_entry(priv, entry); /* Set the current program */ - This->stateBlock->glsl_program = entry; + priv->glsl_program = entry; /* Attach GLSL vshader */ if (vshader_id) { int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */ char tmp_name[10]; + reorder_shader_id = generate_param_reorder_function(vshader, pshader, gl_info); + TRACE("Attaching GLSL shader object %u to program %u\n", reorder_shader_id, programId); + GL_EXTCALL(glAttachObjectARB(programId, reorder_shader_id)); + checkGLcall("glAttachObjectARB"); + /* Flag the reorder function for deletion, then it will be freed automatically when the program + * is destroyed + */ + GL_EXTCALL(glDeleteObjectARB(reorder_shader_id)); + TRACE("Attaching GLSL shader object %u to program %u\n", vshader_id, programId); GL_EXTCALL(glAttachObjectARB(programId, vshader_id)); checkGLcall("glAttachObjectARB"); @@ -3027,15 +3285,6 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use checkGLcall("glBindAttribLocationARB"); list_add_head(&((IWineD3DBaseShaderImpl *)vshader)->baseShader.linked_programs, &entry->vshader_entry); - - reorder_shader_id = generate_param_reorder_function(vshader, pshader, gl_info); - TRACE("Attaching GLSL shader object %u to program %u\n", reorder_shader_id, programId); - GL_EXTCALL(glAttachObjectARB(programId, reorder_shader_id)); - checkGLcall("glAttachObjectARB"); - /* Flag the reorder function for deletion, then it will be freed automatically when the program - * is destroyed - */ - GL_EXTCALL(glDeleteObjectARB(reorder_shader_id)); } /* Attach GLSL pshader */ @@ -3071,15 +3320,33 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use entry->puniformI_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); } + if(pshader) { + for(i = 0; i < ((IWineD3DPixelShaderImpl*)pshader)->numbumpenvmatconsts; i++) { + char name[32]; + sprintf(name, "bumpenvmat%d", ((IWineD3DPixelShaderImpl*)pshader)->bumpenvmatconst[i].texunit); + entry->bumpenvmat_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + sprintf(name, "luminancescale%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit); + entry->luminancescale_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + sprintf(name, "luminanceoffset%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit); + entry->luminanceoffset_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + } + } + + entry->posFixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup")); - entry->bumpenvmat_location = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat")); - entry->luminancescale_location = GL_EXTCALL(glGetUniformLocationARB(programId, "luminancescale")); - entry->luminanceoffset_location = GL_EXTCALL(glGetUniformLocationARB(programId, "luminanceoffset")); entry->srgb_comparison_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_comparison")); entry->srgb_mul_low_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_mul_low")); entry->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(programId, "ycorrection")); checkGLcall("Find glsl program uniform locations"); + if (pshader && WINED3DSHADER_VERSION_MAJOR(((IWineD3DPixelShaderImpl *)pshader)->baseShader.hex_version) >= 3 + && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > GL_LIMITS(glsl_varyings) / 4) { + TRACE("Shader %d needs vertex color clamping disabled\n", programId); + entry->vertex_color_clamp = GL_FALSE; + } else { + entry->vertex_color_clamp = GL_FIXED_ONLY_ARB; + } + /* Set the shader to allow uniform loading on it */ GL_EXTCALL(glUseProgramObjectARB(programId)); checkGLcall("glUseProgramObjectARB(programId)"); @@ -3100,12 +3367,24 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use /* Load pixel shader samplers */ shader_glsl_load_psamplers(gl_info, (IWineD3DStateBlock*)This->stateBlock, programId); } + + /* If the local constants do not have to be loaded with the environment constants, + * load them now to have them hardcoded in the GLSL program. This saves some CPU cycles + * later + */ + if(pshader && !((IWineD3DPixelShaderImpl*)pshader)->baseShader.load_local_constsF) { + hardcode_local_constants((IWineD3DBaseShaderImpl *) pshader, gl_info, programId, 'P'); + } + if(vshader && !((IWineD3DVertexShaderImpl*)vshader)->baseShader.load_local_constsF) { + hardcode_local_constants((IWineD3DBaseShaderImpl *) vshader, gl_info, programId, 'V'); + } } static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; const char *blt_vshader[] = { + "#version 120\n" "void main(void)\n" "{\n" " gl_Position = gl_Vertex;\n" @@ -3116,6 +3395,7 @@ static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) { }; const char *blt_pshader[] = { + "#version 120\n" "uniform sampler2D sampler;\n" "void main(void)\n" "{\n" @@ -3138,18 +3418,38 @@ static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) { print_glsl_info_log(&GLINFO_LOCATION, program_id); + /* Once linked we can mark the shaders for deletion. They will be deleted once the program + * is destroyed + */ + GL_EXTCALL(glDeleteObjectARB(vshader_id)); + GL_EXTCALL(glDeleteObjectARB(pshader_id)); return program_id; } static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; GLhandleARB program_id = 0; + GLenum old_vertex_color_clamp, current_vertex_color_clamp; + + old_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vertex_color_clamp : GL_FIXED_ONLY_ARB; if (useVS || usePS) set_glsl_shader_program(iface, usePS, useVS); - else This->stateBlock->glsl_program = NULL; + else priv->glsl_program = NULL; - program_id = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0; + current_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vertex_color_clamp : GL_FIXED_ONLY_ARB; + + if (old_vertex_color_clamp != current_vertex_color_clamp) { + if (GL_SUPPORT(ARB_COLOR_BUFFER_FLOAT)) { + GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp)); + checkGLcall("glClampColorARB"); + } else { + FIXME("vertex color clamp needs to be changed, but extension not supported.\n"); + } + } + + program_id = priv->glsl_program ? priv->glsl_program->programId : 0; if (program_id) TRACE("Using GLSL program %u\n", program_id); GL_EXTCALL(glUseProgramObjectARB(program_id)); checkGLcall("glUseProgramObjectARB"); @@ -3158,18 +3458,31 @@ static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { static void shader_glsl_select_depth_blt(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - static GLhandleARB program_id = 0; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *) This->shader_priv; static GLhandleARB loc = -1; - if (!program_id) { - program_id = create_glsl_blt_shader(gl_info); - loc = GL_EXTCALL(glGetUniformLocationARB(program_id, "sampler")); + if (!priv->depth_blt_glsl_program_id) { + priv->depth_blt_glsl_program_id = create_glsl_blt_shader(gl_info); + loc = GL_EXTCALL(glGetUniformLocationARB(priv->depth_blt_glsl_program_id, "sampler")); } - GL_EXTCALL(glUseProgramObjectARB(program_id)); + GL_EXTCALL(glUseProgramObjectARB(priv->depth_blt_glsl_program_id)); GL_EXTCALL(glUniform1iARB(loc, 0)); } +static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *) This->shader_priv; + GLhandleARB program_id; + + program_id = priv->glsl_program ? priv->glsl_program->programId : 0; + if (program_id) TRACE("Using GLSL program %u\n", program_id); + + GL_EXTCALL(glUseProgramObjectARB(program_id)); + checkGLcall("glUseProgramObjectARB"); +} + static void shader_glsl_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -3179,7 +3492,9 @@ static void shader_glsl_cleanup(IWineD3DDevice *iface) { static void shader_glsl_destroy(IWineD3DBaseShader *iface) { struct list *linked_programs; IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; - WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *) This->baseShader.device)->adapter->gl_info; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)device->shader_priv; + WineD3D_GL_Info *gl_info = &device->adapter->gl_info; /* Note: Do not use QueryInterface here to find out which shader type this is because this code * can be called from IWineD3DBaseShader::Release @@ -3195,11 +3510,11 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { if(pshader) { LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { - delete_glsl_program_entry(This->baseShader.device, entry); + delete_glsl_program_entry(priv, gl_info, entry); } } else { LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, vshader_entry) { - delete_glsl_program_entry(This->baseShader.device, entry); + delete_glsl_program_entry(priv, gl_info, entry); } } } @@ -3207,13 +3522,282 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { TRACE("Deleting shader object %u\n", This->baseShader.prgId); GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); checkGLcall("glDeleteObjectARB"); + This->baseShader.prgId = 0; + This->baseShader.is_compiled = FALSE; +} + +static unsigned int glsl_program_key_hash(void *key) { + glsl_program_key_t *k = (glsl_program_key_t *)key; + + unsigned int hash = k->vshader | k->pshader << 16; + hash += ~(hash << 15); + hash ^= (hash >> 10); + hash += (hash << 3); + hash ^= (hash >> 6); + hash += ~(hash << 11); + hash ^= (hash >> 16); + + return hash; +} + +static BOOL glsl_program_key_compare(void *keya, void *keyb) { + glsl_program_key_t *ka = (glsl_program_key_t *)keya; + glsl_program_key_t *kb = (glsl_program_key_t *)keyb; + + return ka->vshader == kb->vshader && ka->pshader == kb->pshader; +} + +static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv)); + priv->glsl_program_lookup = hash_table_create(glsl_program_key_hash, glsl_program_key_compare); + This->shader_priv = priv; + return WINED3D_OK; +} + +static void shader_glsl_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv; + + if(priv->depth_blt_glsl_program_id) { + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_glsl_program_id)); + } + + hash_table_destroy(priv->glsl_program_lookup, NULL, NULL); + + HeapFree(GetProcessHeap(), 0, This->shader_priv); + This->shader_priv = NULL; +} + +static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) { + /* TODO: GL_EXT_bindable_uniform can be used to share constants across shaders */ + return FALSE; +} + +static void shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) { + IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; + shader_reg_maps* reg_maps = &This->baseShader.reg_maps; + CONST DWORD *function = This->baseShader.function; + const char *fragcolor; + WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; + + /* Create the hw GLSL shader object and assign it as the baseShader.prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); + + shader_addline(buffer, "#version 120\n"); + + if (GL_SUPPORT(ARB_DRAW_BUFFERS)) { + shader_addline(buffer, "#extension GL_ARB_draw_buffers : enable\n"); + } + if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + /* The spec says that it doesn't have to be explicitly enabled, but the nvidia + * drivers write a warning if we don't do so + */ + shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); + } + + /* Base Declarations */ + shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + + /* Pack 3.0 inputs */ + if (This->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { + + if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed) { + This->vertexprocessing = pretransformed; + pshader_glsl_input_pack(buffer, This->semantics_in, iface); + } else if(!use_vs((IWineD3DDeviceImpl *) This->baseShader.device)) { + This->vertexprocessing = fixedfunction; + pshader_glsl_input_pack(buffer, This->semantics_in, iface); + } else { + This->vertexprocessing = vertexshader; + } + } + + /* Base Shader Body */ + shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); + + /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ + if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */ + if(GL_SUPPORT(ARB_DRAW_BUFFERS)) + shader_addline(buffer, "gl_FragData[0] = R0;\n"); + else + shader_addline(buffer, "gl_FragColor = R0;\n"); + } + + if(GL_SUPPORT(ARB_DRAW_BUFFERS)) { + fragcolor = "gl_FragData[0]"; + } else { + fragcolor = "gl_FragColor"; + } + if(This->srgb_enabled) { + shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n", + fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high, + srgb_sub_high, srgb_sub_high, srgb_sub_high); + shader_addline(buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor); + shader_addline(buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor); + shader_addline(buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor); + shader_addline(buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor); + shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor); + } + /* Pixel shader < 3.0 do not replace the fog stage. + * This implements linear fog computation and blending. + * TODO: non linear fog + * NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but + * -1/(e-s) and e/(e-s) respectively. + */ + if(This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) { + shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n"); + shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); + } + + shader_addline(buffer, "}\n"); + + TRACE("Compiling shader object %u\n", shader_obj); + GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL)); + GL_EXTCALL(glCompileShaderARB(shader_obj)); + print_glsl_info_log(&GLINFO_LOCATION, shader_obj); + + /* Store the shader object */ + This->baseShader.prgId = shader_obj; +} + +static void shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) { + IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; + shader_reg_maps* reg_maps = &This->baseShader.reg_maps; + CONST DWORD *function = This->baseShader.function; + WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; + + /* Create the hw GLSL shader program and assign it as the baseShader.prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + + shader_addline(buffer, "#version 120\n"); + + /* Base Declarations */ + shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + + /* Base Shader Body */ + shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); + + /* Unpack 3.0 outputs */ + if (This->baseShader.hex_version >= WINED3DVS_VERSION(3,0)) { + shader_addline(buffer, "order_ps_input(OUT);\n"); + } else { + shader_addline(buffer, "order_ps_input();\n"); + } + + /* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */ + if (!reg_maps->fog) + shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n"); + + /* Write the final position. + * + * OpenGL coordinates specify the center of the pixel while d3d coords specify + * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains + * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x + * contains 1.0 to allow a mad. + */ + shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n"); + shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n"); + + /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c + * + * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run + * before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w, + * which is the same as z = z * 2 - w. + */ + shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); + + shader_addline(buffer, "}\n"); + + TRACE("Compiling shader object %u\n", shader_obj); + GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL)); + GL_EXTCALL(glCompileShaderARB(shader_obj)); + print_glsl_info_log(&GLINFO_LOCATION, shader_obj); + + /* Store the shader object */ + This->baseShader.prgId = shader_obj; +} + +static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) { + /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati + * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using + * vs_nv_version which is based on NV_vertex_program. + * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not + * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it + * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number + * of native instructions, so use that here. For more info see the pixel shader versioning code below. + */ + if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512)) + pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0); + else + pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); + TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (pCaps->VertexShaderVersion >> 8) & 0xff, pCaps->VertexShaderVersion & 0xff); + pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF); + + /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b. + * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed + * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment + * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info + * in max native instructions. Intel and others also offer the info in this extension but they + * don't support GLSL (at least on Windows). + * + * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number + * of instructions is 512 or less we have to do with ps2.0 hardware. + * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware. + */ + if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512)) + pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0); + else + pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); + + /* FIXME: The following line is card dependent. -8.0 to 8.0 is the + * Direct3D minimum requirement. + * + * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude" + * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here? + * + * The problem is that the refrast clamps temporary results in the shader to + * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here, + * then applications may miss the clamping behavior. On the other hand, if it is smaller, + * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't + * offer a way to query this. + */ + pCaps->PixelShader1xMaxValue = 8.0; + TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (pCaps->PixelShaderVersion >> 8) & 0xff, pCaps->PixelShaderVersion & 0xff); +} + +static BOOL shader_glsl_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt)); + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_Q8W8V8U8: + case WINED3DFMT_ATI2N: + TRACE("[OK]\n"); + return TRUE; + default: + TRACE("[FAILED\n"); + return FALSE; + } } const shader_backend_t glsl_shader_backend = { - &shader_glsl_select, - &shader_glsl_select_depth_blt, - &shader_glsl_load_constants, - &shader_glsl_cleanup, - &shader_glsl_color_correction, - &shader_glsl_destroy + shader_glsl_select, + shader_glsl_select_depth_blt, + shader_glsl_deselect_depth_blt, + shader_glsl_load_constants, + shader_glsl_cleanup, + shader_glsl_color_correction, + shader_glsl_destroy, + shader_glsl_alloc, + shader_glsl_free, + shader_glsl_dirty_const, + shader_glsl_generate_pshader, + shader_glsl_generate_vshader, + shader_glsl_get_caps, + shader_glsl_conv_supported, }; diff --git a/reactos/dll/directx/wine/wined3d/indexbuffer.c b/reactos/dll/directx/wine/wined3d/indexbuffer.c index 62d90d19d1c..a93f8fe2ed7 100644 --- a/reactos/dll/directx/wine/wined3d/indexbuffer.c +++ b/reactos/dll/directx/wine/wined3d/indexbuffer.c @@ -5,6 +5,7 @@ * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber + * Copyright 2007 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -110,6 +111,27 @@ static void WINAPI IWineD3DIndexBufferImpl_PreLoad(IWineD3DIndexBuffer *iface) { IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface); } +static void WINAPI IWineD3DIndexBufferImpl_UnLoad(IWineD3DIndexBuffer *iface) { + IWineD3DIndexBufferImpl *This = (IWineD3DIndexBufferImpl *) iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + TRACE("(%p)\n", This); + + /* This is easy: The whole content is shadowed in This->resource.allocatedMemory, + * so we only have to destroy the vbo. Only do it if we have a vbo, which implies + * that vbos are supported. + * (TODO: Make a IWineD3DBuffer base class for index and vertex buffers and share + * this code. Also needed for D3D10) + */ + if(This->vbo) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); + checkGLcall("glDeleteBuffersARB"); + LEAVE_GL(); + This->vbo = 0; + } +} + static WINED3DRESOURCETYPE WINAPI IWineD3DIndexBufferImpl_GetType(IWineD3DIndexBuffer *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -126,7 +148,7 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Lock(IWineD3DIndexBuffer *iface, U TRACE("(%p) : offset %d, size %d, Flags=%x\n", This, OffsetToLock, SizeToLock, Flags); InterlockedIncrement(&This->lockcount); - *ppbData = (BYTE *)This->resource.allocatedMemory + OffsetToLock; + *ppbData = This->resource.allocatedMemory + OffsetToLock; if(Flags & (WINED3DLOCK_READONLY | WINED3DLOCK_NO_DIRTY_UPDATE) || This->vbo == 0) { return WINED3D_OK; @@ -158,9 +180,7 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface) if(locks == 0 && This->vbo && (This->dirtyend - This->dirtystart) > 0) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - if(device->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, This->vbo)); @@ -203,6 +223,7 @@ const IWineD3DIndexBufferVtbl IWineD3DIndexBuffer_Vtbl = IWineD3DIndexBufferImpl_SetPriority, IWineD3DIndexBufferImpl_GetPriority, IWineD3DIndexBufferImpl_PreLoad, + IWineD3DIndexBufferImpl_UnLoad, IWineD3DIndexBufferImpl_GetType, /* IWineD3DIndexBuffer */ IWineD3DIndexBufferImpl_Lock, diff --git a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c new file mode 100644 index 00000000000..9ebb17b1d05 --- /dev/null +++ b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c @@ -0,0 +1,825 @@ +/* + * Fixed function pipeline replacement using GL_NV_register_combiners + * and GL_NV_texture_shader + * + * Copyright 2006 Henri Verbeet + * Copyright 2008 Stefan Dösinger(for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "config.h" + +#include +#include + +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); + +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +void nvts_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + BOOL bumpmap = FALSE; + + if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE || + stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) { + bumpmap = TRUE; + context->texShaderBumpMap |= (1 << stage); + } else { + context->texShaderBumpMap &= ~(1 << stage); + } + + if(stateblock->textures[stage]) { + switch(stateblock->textureDimensions[stage]) { + case GL_TEXTURE_2D: + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)"); + break; + case GL_TEXTURE_RECTANGLE_ARB: + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)"); + break; + case GL_TEXTURE_3D: + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)"); + break; + case GL_TEXTURE_CUBE_MAP_ARB: + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)"); + break; + } + } else { + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)"); + } +} + +typedef struct { + GLenum input[3]; + GLenum mapping[3]; + GLenum component_usage[3]; +} tex_op_args; + +static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) { + switch (d3dta) { + case WINED3DTA_DIFFUSE: + return GL_PRIMARY_COLOR_NV; + + case WINED3DTA_CURRENT: + if (stage) return GL_SPARE0_NV; + else return GL_PRIMARY_COLOR_NV; + + case WINED3DTA_TEXTURE: + if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx; + else return GL_PRIMARY_COLOR_NV; + + case WINED3DTA_TFACTOR: + return GL_CONSTANT_COLOR0_NV; + + case WINED3DTA_SPECULAR: + return GL_SECONDARY_COLOR_NV; + + case WINED3DTA_TEMP: + return GL_SPARE1_NV; + + case WINED3DTA_CONSTANT: + /* TODO: Support per stage constants (WINED3DTSS_CONSTANT, NV_register_combiners2) */ + FIXME("WINED3DTA_CONSTANT, not properly supported.\n"); + return GL_CONSTANT_COLOR1_NV; + + default: + FIXME("Unrecognized texture arg %#x\n", d3dta); + return GL_TEXTURE; + } +} + +static GLenum invert_mapping(GLenum mapping) { + if (mapping == GL_UNSIGNED_INVERT_NV) return GL_UNSIGNED_IDENTITY_NV; + else if (mapping == GL_UNSIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV; + + FIXME("Unhandled mapping %#x\n", mapping); + return mapping; +} + +static void get_src_and_opr_nvrc(DWORD stage, DWORD arg, BOOL is_alpha, GLenum* input, GLenum* mapping, GLenum *component_usage, INT texture_idx) { + /* The WINED3DTA_COMPLEMENT flag specifies the complement of the input should + * be used. */ + if (arg & WINED3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV; + else *mapping = GL_UNSIGNED_IDENTITY_NV; /* Clamp all values to positive ranges */ + + /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the input + * should be used for all input components. */ + if (is_alpha || arg & WINED3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA; + else *component_usage = GL_RGB; + + *input = d3dta_to_combiner_input(arg & WINED3DTA_SELECTMASK, stage, texture_idx); +} + +void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx, DWORD dst) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface; + tex_op_args tex_op_args = {{0}, {0}, {0}}; + 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); + + /* If a texture stage references an invalid texture unit the stage just + * passes through the result from the previous stage */ + if (is_invalid_op(This, stage, op, arg1, arg2, arg3)) { + arg1 = WINED3DTA_CURRENT; + op = WINED3DTOP_SELECTARG1; + } + + get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0], + &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx); + get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1], + &tex_op_args.mapping[1], &tex_op_args.component_usage[1], texture_idx); + get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2], + &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx); + + + if(dst == WINED3DTA_TEMP) { + output = GL_SPARE1_NV; + } else { + output = GL_SPARE0_NV; + } + + /* This is called by a state handler which has the gl lock held and a context for the thread */ + switch(op) + { + case WINED3DTOP_DISABLE: + /* Only for alpha */ + if (!is_alpha) ERR("Shouldn't be called for WINED3DTSS_COLOROP (WINED3DTOP_DISABLE)\n"); + /* Input, prev_alpha*1 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_SELECTARG1: + case WINED3DTOP_SELECTARG2: + /* Input, arg*1 */ + if (op == WINED3DTOP_SELECTARG1) { + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + } else { + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + } + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_MODULATE: + case WINED3DTOP_MODULATE2X: + case WINED3DTOP_MODULATE4X: + /* Input, arg1*arg2 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + + /* Output */ + if (op == WINED3DTOP_MODULATE) { + GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == WINED3DTOP_MODULATE2X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV, + GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == WINED3DTOP_MODULATE4X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV, + GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } + break; + + case WINED3DTOP_ADD: + case WINED3DTOP_ADDSIGNED: + case WINED3DTOP_ADDSIGNED2X: + /* Input, arg1*1+arg2*1 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + if (op == WINED3DTOP_ADD) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == WINED3DTOP_ADDSIGNED) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == WINED3DTOP_ADDSIGNED2X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); + } + break; + + case WINED3DTOP_SUBTRACT: + /* Input, arg1*1+-arg2*1 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[1], GL_SIGNED_NEGATE_NV, tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_ADDSMOOTH: + /* Input, arg1*1+(1-arg1)*arg2 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_BLENDDIFFUSEALPHA: + case WINED3DTOP_BLENDTEXTUREALPHA: + case WINED3DTOP_BLENDFACTORALPHA: + case WINED3DTOP_BLENDTEXTUREALPHAPM: + case WINED3DTOP_BLENDCURRENTALPHA: + { + GLenum alpha_src = GL_PRIMARY_COLOR_NV; + if (op == WINED3DTOP_BLENDDIFFUSEALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_DIFFUSE, stage, texture_idx); + else if (op == WINED3DTOP_BLENDTEXTUREALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx); + else if (op == WINED3DTOP_BLENDFACTORALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TFACTOR, stage, texture_idx); + else if (op == WINED3DTOP_BLENDTEXTUREALPHAPM) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx); + else if (op == WINED3DTOP_BLENDCURRENTALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_CURRENT, stage, texture_idx); + else FIXME("Unhandled WINED3DTOP %s, shouldn't happen\n", debug_d3dtop(op)); + + /* Input, arg1*alpha_src+arg2*(1-alpha_src) */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + if (op == WINED3DTOP_BLENDTEXTUREALPHAPM) + { + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + } else { + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + alpha_src, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA)); + } + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + alpha_src, GL_UNSIGNED_INVERT_NV, GL_ALPHA)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + } + + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */ + if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEALPHA_ADDCOLOR)\n"); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */ + if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATECOLOR_ADDALPHA)\n"); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */ + if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVALPHA_ADDCOLOR)\n"); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), GL_ALPHA)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */ + if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVCOLOR_ADDALPHA)\n"); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_DOTPRODUCT3: + /* Input, arg1 . arg2 */ + /* FIXME: DX7 uses a different calculation? */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[0], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[1], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[1])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_MULTIPLYADD: + /* Input, arg3*1+arg1*arg2 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_LERP: + /* Input, arg3*arg1+(1-arg3)*arg2 */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, + tex_op_args.input[2], invert_mapping(tex_op_args.mapping[2]), tex_op_args.component_usage[2])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case WINED3DTOP_BUMPENVMAPLUMINANCE: + case WINED3DTOP_BUMPENVMAP: + if(GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* The bump map stage itself isn't exciting, just read the texture. But tell the next stage to + * perform bump mapping and source from the current stage. Pretty much a SELECTARG2. + * ARG2 is passed through unmodified(apps will most likely use D3DTA_CURRENT for arg2, arg1 + * (which will most likely be D3DTA_TEXTURE) is available as a texture shader input for the next stage + */ + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, + tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); + GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, + GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); + /* Always pass through to CURRENT, ignore temp arg */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + } + + default: + FIXME("Unhandled WINED3DTOP: stage %d, is_alpha %d, op %s (%#x), arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n", + stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx); + } + + checkGLcall("set_tex_op_nvrc()\n"); + +} + + +static void nvrc_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; + BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage]; + + TRACE("Setting color op for stage %d\n", stage); + + if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && + ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) { + /* Using a pixel shader? Don't care for anything here, the shader applying does it */ + return; + } + + if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage); + + if (mapped_stage != -1) { + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + if (tex_used && mapped_stage >= GL_LIMITS(textures)) { + FIXME("Attempt to enable unsupported stage!\n"); + return; + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + } else if (stage > 0) { + WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + return; + } + } + + if(stateblock->lowest_disabled_stage > 0) { + glEnable(GL_REGISTER_COMBINERS_NV); + GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage)); + } else { + glDisable(GL_REGISTER_COMBINERS_NV); + } + if(stage >= stateblock->lowest_disabled_stage) { + TRACE("Stage disabled\n"); + if (mapped_stage != -1) { + /* Disable everything here */ + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) { + glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE); + } + } + /* All done */ + return; + } + + /* The sampler will also activate the correct texture dimensions, so no need to do it here + * if the sampler for this stage is dirty + */ + if(!isStateDirty(context, STATE_SAMPLER(stage))) { + if (tex_used) { + if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { + nvts_activate_dimensions(stage, stateblock, context); + } else { + texture_activate_dimensions(stage, stateblock, context); + } + } + } + + /* Set the texture combiners */ + set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, + stateblock->textureState[stage][WINED3DTSS_COLOROP], + stateblock->textureState[stage][WINED3DTSS_COLORARG1], + stateblock->textureState[stage][WINED3DTSS_COLORARG2], + stateblock->textureState[stage][WINED3DTSS_COLORARG0], + mapped_stage, + stateblock->textureState[stage][WINED3DTSS_RESULTARG]); + + /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set, + * thus the texture shader may have to be updated + */ + if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { + BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE || + stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE; + BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE; + if(usesBump != usedBump) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1)); + checkGLcall("glActiveTextureARB"); + nvts_activate_dimensions(stage + 1, stateblock, context); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + } + } +} + +void nvts_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD sampler = state - STATE_SAMPLER(0); + DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler]; + + /* No need to enable / disable anything here for unused samplers. The tex_colorop + * handler takes care. Also no action is needed with pixel shaders, or if tex_colorop + * will take care of this business + */ + if(mapped_stage == -1 || mapped_stage >= GL_LIMITS(textures)) return; + if(sampler >= stateblock->lowest_disabled_stage) return; + if(isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) return; + + nvts_activate_dimensions(sampler, stateblock, context); +} + +static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1]; + float mat[2][2]; + + /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to + * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump + * map offsetting is done in the stage reading the bump mapped texture, and the perturbation + * 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 < GL_LIMITS(textures)) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))"); + + /* We can't just pass a pointer to the stateblock to GL due to the different matrix + * format(column major vs row major) + */ + mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); + mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]); + mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]); + mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]); + glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *) mat); + checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)"); + } +} + +static void nvrc_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float col[4]; + D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); + GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0])); +} +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION (*gl_info) +static void nvrc_enable(IWineD3DDevice *iface, BOOL enable) { } + +static void nvts_enable(IWineD3DDevice *iface, BOOL enable) { + if(enable) { + glEnable(GL_TEXTURE_SHADER_NV); + checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); + } else { + glDisable(GL_TEXTURE_SHADER_NV); + checkGLcall("glDisable(GL_TEXTURE_SHADER_NV)"); + } +} + +static void nvrc_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) { + pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | + WINED3DTEXOPCAPS_ADDSIGNED | + WINED3DTEXOPCAPS_ADDSIGNED2X | + WINED3DTEXOPCAPS_MODULATE | + WINED3DTEXOPCAPS_MODULATE2X | + WINED3DTEXOPCAPS_MODULATE4X | + WINED3DTEXOPCAPS_SELECTARG1 | + WINED3DTEXOPCAPS_SELECTARG2 | + WINED3DTEXOPCAPS_DISABLE | + WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | + WINED3DTEXOPCAPS_BLENDFACTORALPHA | + WINED3DTEXOPCAPS_BLENDCURRENTALPHA | + WINED3DTEXOPCAPS_LERP | + WINED3DTEXOPCAPS_SUBTRACT | + WINED3DTEXOPCAPS_ADDSMOOTH | + WINED3DTEXOPCAPS_MULTIPLYADD | + WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM | + WINED3DTEXOPCAPS_DOTPRODUCT3 | + WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA; + + if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { + /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does + * not support 3D textures. This asks for trouble if an app uses both bump mapping + * and 3D textures. It also allows us to keep the code simpler by having texture + * shaders constantly enabled. + */ + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP; + /* TODO: Luminance bump map? */ + } + +#if 0 + /* FIXME: Add + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE + WINED3DTEXOPCAPS_PREMODULATE */ +#endif + + pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages); + pCaps->MaxSimultaneousTextures = GL_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_SUPPORT(NV_REGISTER_COMBINERS2)) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; +#endif +} + +static HRESULT nvrc_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +static void nvrc_fragment_free(IWineD3DDevice *iface) {} + +/* Two fixed function pipeline implementations using GL_NV_register_combiners and + * GL_NV_texture_shader. The nvts_fragment_pipeline assumes that both extensions + * are available(geforce 3 and newer), while nvrc_fragment_pipeline uses only the + * register combiners extension(Pre-GF3). + */ + +static BOOL nvts_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s: [FAILED]\n", debug_d3dformat(fmt)); + return FALSE; +} + +const struct StateEntryTemplate nvrc_fragmentstate_template[] = { + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { 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 }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, 0 }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 }, + { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), nvrc_texfactor }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), nvts_texdim }, NV_TEXTURE_SHADER2 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; + +const struct fragment_pipeline nvts_fragment_pipeline = { + nvts_enable, + nvrc_fragment_get_caps, + nvrc_fragment_alloc, + nvrc_fragment_free, + nvts_conv_supported, + nvrc_fragmentstate_template, + FALSE /* we cannot disable projected textures. The vertex pipe has to do it */ +}; + +const struct fragment_pipeline nvrc_fragment_pipeline = { + nvrc_enable, + nvrc_fragment_get_caps, + nvrc_fragment_alloc, + nvrc_fragment_free, + nvts_conv_supported, + nvrc_fragmentstate_template, + FALSE /* we cannot disable projected textures. The vertex pipe has to do it */ +}; diff --git a/reactos/dll/directx/wine/wined3d/palette.c b/reactos/dll/directx/wine/wined3d/palette.c index 506b4fe0630..95b8da9e7fc 100644 --- a/reactos/dll/directx/wine/wined3d/palette.c +++ b/reactos/dll/directx/wine/wined3d/palette.c @@ -63,6 +63,7 @@ static ULONG WINAPI IWineD3DPaletteImpl_Release(IWineD3DPalette *iface) { TRACE("(%p)->() decrementing from %u.\n", This, ref + 1); if (!ref) { + DeleteObject(This->hpal); HeapFree(GetProcessHeap(), 0, This); return 0; } @@ -110,6 +111,7 @@ static HRESULT WINAPI IWineD3DPaletteImpl_SetEntries(IWineD3DPalette *iface, DW IWineD3DResourceImpl *res; TRACE("(%p)->(%08x,%d,%d,%p)\n",This,Flags,Start,Count,PalEnt); + TRACE("Palette flags: %#x\n", This->Flags); if (This->Flags & WINEDDPCAPS_8BITENTRIES) { unsigned int i; @@ -121,6 +123,19 @@ static HRESULT WINAPI IWineD3DPaletteImpl_SetEntries(IWineD3DPalette *iface, DW else { memcpy(This->palents+Start, PalEnt, Count * sizeof(PALETTEENTRY)); + /* When WINEDDCAPS_ALLOW256 isn't set we need to override entry 0 with black and 255 with white */ + if(!(This->Flags & WINEDDPCAPS_ALLOW256)) + { + TRACE("WINEDDPCAPS_ALLOW256 set, overriding palette entry 0 with black and 255 with white\n"); + This->palents[0].peRed = 0; + This->palents[0].peGreen = 0; + This->palents[0].peBlue = 0; + + This->palents[255].peRed = 255; + This->palents[255].peGreen = 255; + This->palents[255].peBlue = 255; + } + if (This->hpal) SetPaletteEntries(This->hpal, Start, Count, This->palents+Start); } @@ -142,17 +157,6 @@ static HRESULT WINAPI IWineD3DPaletteImpl_SetEntries(IWineD3DPalette *iface, DW } } - /* If the palette is the primary palette, set the entries to the device */ - if(This->Flags & WINEDDPCAPS_PRIMARYSURFACE) { - unsigned int i; - IWineD3DDeviceImpl *device = This->wineD3DDevice; - PALETTEENTRY *entry = PalEnt; - - for(i = Start; i < Start+Count; i++) { - device->palettes[device->currentPalette][i] = *entry++; - } - } - return WINED3D_OK; } @@ -168,8 +172,8 @@ static HRESULT WINAPI IWineD3DPaletteImpl_GetParent(IWineD3DPalette *iface, IUn IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface; TRACE("(%p)->(%p)\n", This, Parent); - *Parent = (IUnknown *) This->parent; - IUnknown_AddRef( (IUnknown *) This->parent); + *Parent = This->parent; + IUnknown_AddRef(This->parent); return WINED3D_OK; } diff --git a/reactos/dll/directx/wine/wined3d/pixelshader.c b/reactos/dll/directx/wine/wined3d/pixelshader.c index b9fbd75482d..29cd36891cc 100644 --- a/reactos/dll/directx/wine/wined3d/pixelshader.c +++ b/reactos/dll/directx/wine/wined3d/pixelshader.c @@ -6,6 +6,7 @@ * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber * Copyright 2006 Ivan Gyurdiev + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,14 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DDeviceImpl *) This->baseShader.device)->adapter->gl_info -#if 0 /* Must not be 1 in cvs version */ -# define PSTRACE(A) TRACE A -# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w) -#else -# define PSTRACE(A) -# define TRACE_VSVECTOR(name) -#endif - #define GLNAME_REQUIRE_GLSL ((const char *)1) static HRESULT WINAPI IWineD3DPixelShaderImpl_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, LPVOID *ppobj) { @@ -105,7 +98,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader* } CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { - /* Arithmethic */ + /* Arithmetic */ {WINED3DSIO_NOP, "nop", "NOP", 0, 0, pshader_hw_map2gl, NULL, 0, 0}, {WINED3DSIO_MOV, "mov", "MOV", 1, 2, pshader_hw_map2gl, shader_glsl_mov, 0, 0}, {WINED3DSIO_ADD, "add", "ADD", 1, 3, pshader_hw_map2gl, shader_glsl_arith, 0, 0}, @@ -280,10 +273,7 @@ static void pshader_set_limits( /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB or GLSL and send it to the card */ static inline VOID IWineD3DPixelShaderImpl_GenerateShader( - IWineD3DPixelShader *iface, - shader_reg_maps* reg_maps, - CONST DWORD *pFunction) { - + IWineD3DPixelShader *iface) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; SHADER_BUFFER buffer; @@ -303,175 +293,7 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader( buffer.lineNo = 0; buffer.newline = TRUE; - if (This->baseShader.shader_mode == SHADER_GLSL) { - - /* Create the hw GLSL shader object and assign it as the baseShader.prgId */ - GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); - - if (GL_SUPPORT(ARB_DRAW_BUFFERS)) { - shader_addline(&buffer, "#extension GL_ARB_draw_buffers : enable\n"); - } - - /* Base Declarations */ - shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION); - - /* Pack 3.0 inputs */ - if (This->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { - - if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed) { - This->vertexprocessing = pretransformed; - pshader_glsl_input_pack(&buffer, This->semantics_in, iface); - } else if(!use_vs((IWineD3DDeviceImpl *) This->baseShader.device)) { - This->vertexprocessing = fixedfunction; - pshader_glsl_input_pack(&buffer, This->semantics_in, iface); - } else { - This->vertexprocessing = vertexshader; - } - } - - /* Base Shader Body */ - shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction); - - /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ - if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { - /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */ - if(GL_SUPPORT(ARB_DRAW_BUFFERS)) - shader_addline(&buffer, "gl_FragData[0] = R0;\n"); - else - shader_addline(&buffer, "gl_FragColor = R0;\n"); - } - - /* Pixel shader < 3.0 do not replace the fog stage. - * This implements linear fog computation and blending. - * TODO: non linear fog - * NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but - * -1/(e-s) and e/(e-s) respectively. - */ - if(This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) { - shader_addline(&buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n"); - if(GL_SUPPORT(ARB_DRAW_BUFFERS)) - shader_addline(&buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); - else - shader_addline(&buffer, "gl_FragColor.xyz = mix(gl_Fog.color.xyz, gl_FragColor.xyz, Fog);\n"); - } - if(This->srgb_enabled) { - const char *fragcolor; - - if(GL_SUPPORT(ARB_DRAW_BUFFERS)) { - fragcolor = "gl_FragData[0]"; - } else { - fragcolor = "gl_FragColor"; - } - shader_addline(&buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n", - fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high, - srgb_sub_high, srgb_sub_high, srgb_sub_high); - shader_addline(&buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor); - shader_addline(&buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor); - shader_addline(&buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor); - shader_addline(&buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor); - shader_addline(&buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor); - } - - shader_addline(&buffer, "}\n"); - - TRACE("Compiling shader object %u\n", shader_obj); - GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL)); - GL_EXTCALL(glCompileShaderARB(shader_obj)); - print_glsl_info_log(&GLINFO_LOCATION, shader_obj); - - /* Store the shader object */ - This->baseShader.prgId = shader_obj; - - } else if (This->baseShader.shader_mode == SHADER_ARB) { - /* Create the hw ARB shader */ - shader_addline(&buffer, "!!ARBfp1.0\n"); - - shader_addline(&buffer, "TEMP TMP;\n"); /* Used in matrix ops */ - shader_addline(&buffer, "TEMP TMP2;\n"); /* Used in matrix ops */ - shader_addline(&buffer, "TEMP TA;\n"); /* Used for modifiers */ - shader_addline(&buffer, "TEMP TB;\n"); /* Used for modifiers */ - shader_addline(&buffer, "TEMP TC;\n"); /* Used for modifiers */ - 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"); - - /* Base Declarations */ - shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION); - - /* We need two variables for fog blending */ - shader_addline(&buffer, "TEMP TMP_FOG;\n"); - if (This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)) { - shader_addline(&buffer, "TEMP TMP_COLOR;\n"); - } - - /* Base Shader Body */ - shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction); - - /* calculate fog and blend it - * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but - * -1/(e-s) and e/(e-s) respectively. - */ - shader_addline(&buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n"); - - if(This->srgb_enabled) { - if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { - shader_addline(&buffer, "LRP TMP_COLOR.rgb, TMP_FOG.x, R0, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, R0.a;\n"); - } else { - shader_addline(&buffer, "LRP TMP_COLOR.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n"); - } - /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ - - /* Calculate the > 0.0031308 case */ - shader_addline(&buffer, "POW TMP.x, TMP_COLOR.x, srgb_pow.x;\n"); - shader_addline(&buffer, "POW TMP.y, TMP_COLOR.y, srgb_pow.y;\n"); - shader_addline(&buffer, "POW TMP.z, TMP_COLOR.z, srgb_pow.z;\n"); - shader_addline(&buffer, "MUL TMP, TMP, srgb_mul_hi;\n"); - shader_addline(&buffer, "SUB TMP, TMP, srgb_sub_hi;\n"); - /* Calculate the < case */ - shader_addline(&buffer, "MUL TMP2, srgb_mul_low, TMP_COLOR;\n"); - /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */ - shader_addline(&buffer, "SLT TA, srgb_comparison, TMP_COLOR;\n"); - shader_addline(&buffer, "SGE TB, srgb_comparison, TMP_COLOR;\n"); - /* Store the components > 0.0031308 in the destination */ - shader_addline(&buffer, "MUL TMP_COLOR, TMP, TA;\n"); - /* Add the components that are < 0.0031308 */ - shader_addline(&buffer, "MAD result.color.xyz, TMP2, TB, TMP_COLOR;\n"); - /* [0.0;1.0] clamping. Not needed, this is done implicitly */ - } else { - if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { - shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, R0, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, R0.a;\n"); - } else { - shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n"); - } - } - - shader_addline(&buffer, "END\n"); - - /* TODO: change to resource.glObjectHandle or something like that */ - GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId)); - - TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId)); - - TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId); - /* Create the program and check for errors */ - GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - buffer.bsize, buffer.buffer)); - - if (glGetError() == GL_INVALID_OPERATION) { - GLint errPos; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); - FIXME("HW PixelShader Error at position %d: %s\n", - errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); - This->baseShader.prgId = -1; - } - } - - This->needsbumpmat = reg_maps->bumpmat; + ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_pshader(iface, &buffer); #if 1 /* if were using the data buffer of device then we don't need to free it */ HeapFree(GetProcessHeap(), 0, buffer.buffer); @@ -514,7 +336,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i } /* Don't do any register mapping magic if it is not needed, or if we can't - * achive anything anyway + * achieve anything anyway */ if(highest_reg_used < (GL_LIMITS(glsl_varyings) / 4) || num_regs_used > (GL_LIMITS(glsl_varyings) / 4) ) { @@ -529,6 +351,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i for(i = 0; i < MAX_REG_INPUT; i++) { This->input_reg_map[i] = i; } + This->declared_in_count = highest_reg_used + 1; } else { j = 0; for(i = 0; i < MAX_REG_INPUT; i++) { @@ -539,6 +362,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i This->input_reg_map[i] = -1; } } + This->declared_in_count = j; } } This->baseShader.load_local_constsF = FALSE; @@ -608,10 +432,11 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader } } if(This->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { - if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed && - This->vertexprocessing != pretransformed) { - WARN("Recompiling shader because pretransformed vertices are provided, which wasn't the case before\n"); - goto recompile; + if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed) { + if(This->vertexprocessing != pretransformed) { + WARN("Recompiling shader because pretransformed vertices are provided, which wasn't the case before\n"); + goto recompile; + } } else if(!use_vs((IWineD3DDeviceImpl *) This->baseShader.device) && This->vertexprocessing != fixedfunction) { WARN("Recompiling shader because fixed function vp is in use, which wasn't the case before\n"); @@ -657,7 +482,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader /* Generate the HW shader */ TRACE("(%p) : Generating hardware program\n", This); - IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function); + IWineD3DPixelShaderImpl_GenerateShader(iface); This->baseShader.is_compiled = TRUE; diff --git a/reactos/dll/directx/wine/wined3d/query.c b/reactos/dll/directx/wine/wined3d/query.c index 7c91f2ee663..45e35b73b0a 100644 --- a/reactos/dll/directx/wine/wined3d/query.c +++ b/reactos/dll/directx/wine/wined3d/query.c @@ -2,8 +2,7 @@ * IWineD3DQuery implementation * * Copyright 2005 Oliver Stieber - * - * + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,8 +24,6 @@ #include "wined3d_private.h" /* - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/Queries.asp - * * Occlusion Queries: * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt @@ -65,6 +62,7 @@ static ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) { TRACE("(%p) : Releasing from %d\n", This, This->ref); ref = InterlockedDecrement(&This->ref); if (ref == 0) { + ENTER_GL(); if(This->type == WINED3DQUERYTYPE_EVENT) { if(GL_SUPPORT(APPLE_FENCE)) { GL_EXTCALL(glDeleteFencesAPPLE(1, &((WineQueryEventData *)(This->extendedData))->fenceId)); @@ -77,6 +75,7 @@ static ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) { GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId)); checkGLcall("glDeleteQueriesARB"); } + LEAVE_GL(); HeapFree(GetProcessHeap(), 0, This->extendedData); HeapFree(GetProcessHeap(), 0, This); @@ -111,13 +110,6 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa TRACE("(%p) : type %#x, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, This->type, pData, dwSize, dwGetDataFlags); - if(dwSize == 0){ - /*you can use this method to poll the resource for the query status*/ - /*We return success(S_OK) if we support a feature, and faikure(S_FALSE) if we don't, just return success and fluff it for now*/ - return S_OK; - }else{ - } - switch (This->type){ case WINED3DQUERYTYPE_VCACHE: @@ -125,6 +117,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_VCACHE *data = (WINED3DDEVINFO_VCACHE *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VCACHE\n", This); + if(pData == NULL || dwSize == 0) break; data->Pattern = WINEMAKEFOURCC('C','A','C','H'); data->OptMethod = 0; /*0 get longest strips, 1 optimize vertex cache*/ data->CacheSize = 0; /*cache size, only required if OptMethod == 1*/ @@ -137,9 +130,10 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_RESOURCEMANAGER *data = (WINED3DDEVINFO_RESOURCEMANAGER *)pData; int i; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_RESOURCEMANAGER\n", This); + if(pData == NULL || dwSize == 0) break; for(i = 0; i < WINED3DRTYPECOUNT; i++){ /*I'm setting the default values to 1 so as to reduce the risk of a div/0 in the caller*/ - /* isTextureResident could be used to get some of this infomration */ + /* isTextureResident could be used to get some of this information */ data->stats[i].bThrashing = FALSE; data->stats[i].ApproxBytesDownloaded = 1; data->stats[i].NumEvicts = 1; @@ -159,65 +153,17 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa { WINED3DDEVINFO_VERTEXSTATS *data = (WINED3DDEVINFO_VERTEXSTATS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXSTATS\n", This); + if(pData == NULL || dwSize == 0) break; data->NumRenderedTriangles = 1; data->NumExtraClippingTriangles = 1; } break; - case WINED3DQUERYTYPE_EVENT: - { - BOOL* data = pData; - WineD3DContext *ctx = ((WineQueryEventData *)This->extendedData)->ctx; - if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { - /* See comment in IWineD3DQuery::Issue, event query codeblock */ - WARN("Query context not active, reporting GPU idle\n"); - *data = TRUE; - } else if(GL_SUPPORT(APPLE_FENCE)) { - *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId)); - checkGLcall("glTestFenceAPPLE"); - } else if(GL_SUPPORT(NV_FENCE)) { - *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId)); - checkGLcall("glTestFenceNV"); - } else { - WARN("(%p): reporting GPU idle\n", This); - *data = TRUE; - } - } - break; - case WINED3DQUERYTYPE_OCCLUSION: - { - DWORD* data = pData; - if (GL_SUPPORT(ARB_OCCLUSION_QUERY) && - ((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext && - This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) { - GLuint available; - GLuint samples; - GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId; - - GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); - checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n"); - TRACE("(%p) : available %d.\n", This, available); - - if (available) { - GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples)); - checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n"); - TRACE("(%p) : Returning %d samples.\n", This, samples); - *data = samples; - res = S_OK; - } else { - res = S_FALSE; - } - } else { - WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This); - *data = 1; - res = S_OK; - } - } - break; case WINED3DQUERYTYPE_TIMESTAMP: { UINT64* data = pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMP\n", This); + if(pData == NULL || dwSize == 0) break; *data = 1; /*Don't know what this is supposed to be*/ } break; @@ -225,6 +171,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa { BOOL* data = pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPDISJOINT\n", This); + if(pData == NULL || dwSize == 0) break; *data = FALSE; /*Don't know what this is supposed to be*/ } break; @@ -232,6 +179,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa { UINT64* data = pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPFREQ\n", This); + if(pData == NULL || dwSize == 0) break; *data = 1; /*Don't know what this is supposed to be*/ } break; @@ -239,6 +187,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa { WINED3DDEVINFO_PIPELINETIMINGS *data = (WINED3DDEVINFO_PIPELINETIMINGS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIPELINETIMINGS\n", This); + if(pData == NULL || dwSize == 0) break; data->VertexProcessingTimePercent = 1.0f; data->PixelProcessingTimePercent = 1.0f; @@ -251,6 +200,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_INTERFACETIMINGS *data = (WINED3DDEVINFO_INTERFACETIMINGS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_INTERFACETIMINGS\n", This); + if(pData == NULL || dwSize == 0) break; data->WaitingForGPUToUseApplicationResourceTimePercent = 1.0f; data->WaitingForGPUToAcceptMoreCommandsTimePercent = 1.0f; data->WaitingForGPUToStayWithinLatencyTimePercent = 1.0f; @@ -264,6 +214,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXTIMINGS\n", This); + if(pData == NULL || dwSize == 0) break; data->MemoryProcessingPercent = 50.0f; data->ComputationProcessingPercent = 50.0f; @@ -274,6 +225,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIXELTIMINGS\n", This); + if(pData == NULL || dwSize == 0) break; data->MemoryProcessingPercent = 50.0f; data->ComputationProcessingPercent = 50.0f; } @@ -283,6 +235,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_BANDWIDTHTIMINGS *data = (WINED3DDEVINFO_BANDWIDTHTIMINGS *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_BANDWIDTHTIMINGS\n", This); + if(pData == NULL || dwSize == 0) break; data->MaxBandwidthUtilized = 1.0f; data->FrontEndUploadMemoryUtilizedPercent = 1.0f; data->VertexRateUtilizedPercent = 1.0f; @@ -295,6 +248,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa WINED3DDEVINFO_CACHEUTILIZATION *data = (WINED3DDEVINFO_CACHEUTILIZATION *)pData; FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_CACHEUTILIZATION\n", This); + if(pData == NULL || dwSize == 0) break; data->TextureCacheHitRate = 1.0f; data->PostTransformVertexCacheHitRate = 1.0f; } @@ -312,6 +266,83 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa return res; /* S_OK if the query data is available*/ } +static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; + DWORD* data = pData; + HRESULT res; + TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); + + if(This->state == QUERY_CREATED) { + /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */ + TRACE("Query wasn't yet started, returning S_OK\n"); + res = S_OK; + if(data) *data = 0; + } else if(This->state == QUERY_BUILDING) { + /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ + TRACE("Query is building, returning S_FALSE\n"); + res = S_FALSE; + } else if (GL_SUPPORT(ARB_OCCLUSION_QUERY) && + ((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext && + This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) { + GLuint available; + GLuint samples; + GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId; + + ENTER_GL(); + GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n"); + TRACE("(%p) : available %d.\n", This, available); + + if (available) { + if(data) { + GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n"); + TRACE("(%p) : Returning %d samples.\n", This, samples); + *data = samples; + } + res = S_OK; + } else { + res = S_FALSE; + } + LEAVE_GL(); + } else { + WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This); + *data = 1; + res = S_OK; + } + return res; +} + +static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; + BOOL* data = pData; + WineD3DContext *ctx; + TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); + + ctx = ((WineQueryEventData *)This->extendedData)->ctx; + if(pData == NULL || dwSize == 0) { + return S_OK; + } if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { + /* See comment in IWineD3DQuery::Issue, event query codeblock */ + WARN("Query context not active, reporting GPU idle\n"); + *data = TRUE; + } else if(GL_SUPPORT(APPLE_FENCE)) { + ENTER_GL(); + *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId)); + checkGLcall("glTestFenceAPPLE"); + LEAVE_GL(); + } else if(GL_SUPPORT(NV_FENCE)) { + ENTER_GL(); + *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId)); + checkGLcall("glTestFenceNV"); + LEAVE_GL(); + } else { + WARN("(%p): reporting GPU idle\n", This); + *data = TRUE; + } + + return S_OK; +} static DWORD WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){ IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; @@ -330,9 +361,6 @@ static DWORD WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){ case WINED3DQUERYTYPE_EVENT: dataSize = sizeof(BOOL); break; - case WINED3DQUERYTYPE_OCCLUSION: - dataSize = sizeof(DWORD); - break; case WINED3DQUERYTYPE_TIMESTAMP: dataSize = sizeof(UINT64); break; @@ -367,6 +395,17 @@ static DWORD WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){ return dataSize; } +static DWORD WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){ + TRACE("(%p) : type D3DQUERY_EVENT\n", iface); + + return sizeof(BOOL); +} + +static DWORD WINAPI IWineD3DOcclusionQueryImpl_GetDataSize(IWineD3DQuery* iface){ + TRACE("(%p) : type D3DQUERY_OCCLUSION\n", iface); + + return sizeof(DWORD); +} static WINED3DQUERYTYPE WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){ IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; @@ -374,62 +413,102 @@ static WINED3DQUERYTYPE WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){ } +static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; + + TRACE("(%p) : dwIssueFlags %#x, type D3DQUERY_EVENT\n", This, dwIssueFlags); + if (dwIssueFlags & WINED3DISSUE_END) { + WineD3DContext *ctx = ((WineQueryEventData *)This->extendedData)->ctx; + if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { + /* GL fences can be used only from the context that created them, + * so if a different context is active, don't bother setting the query. The penalty + * of a context switch is most likely higher than the gain of a correct query result + * + * If the query is used from a different thread, don't bother creating a multithread + * context - there's no point in doing that as the query would be unusable anyway + */ + WARN("Query context not active\n"); + } else if(GL_SUPPORT(APPLE_FENCE)) { + ENTER_GL(); + GL_EXTCALL(glSetFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId)); + checkGLcall("glSetFenceAPPLE"); + LEAVE_GL(); + } else if (GL_SUPPORT(NV_FENCE)) { + ENTER_GL(); + GL_EXTCALL(glSetFenceNV(((WineQueryEventData *)This->extendedData)->fenceId, GL_ALL_COMPLETED_NV)); + checkGLcall("glSetFenceNV"); + LEAVE_GL(); + } + } else if(dwIssueFlags & WINED3DISSUE_BEGIN) { + /* Started implicitly at device creation */ + ERR("Event query issued with START flag - what to do?\n"); + } + + if(dwIssueFlags & WINED3DISSUE_BEGIN) { + This->state = QUERY_BUILDING; + } else { + This->state = QUERY_SIGNALLED; + } + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; + + if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) { + WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx; + + if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { + WARN("Not the owning context, can't start query\n"); + } else { + ENTER_GL(); + /* This is allowed according to msdn and our tests. Reset the query and restart */ + if (dwIssueFlags & WINED3DISSUE_BEGIN) { + if(This->state == QUERY_BUILDING) { + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + } + + GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId)); + checkGLcall("glBeginQuery()"); + } + if (dwIssueFlags & WINED3DISSUE_END) { + /* Msdn says _END on a non-building occlusion query returns an error, but + * our tests show that it returns OK. But OpenGL doesn't like it, so avoid + * generating an error + */ + if(This->state == QUERY_BUILDING) { + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + } + } + LEAVE_GL(); + } + } else { + FIXME("(%p) : Occlusion queries not supported\n", This); + } + + if(dwIssueFlags & WINED3DISSUE_BEGIN) { + This->state = QUERY_BUILDING; + } else { + This->state = QUERY_SIGNALLED; + } + return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ +} + static HRESULT WINAPI IWineD3DQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags){ IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; TRACE("(%p) : dwIssueFlags %#x, type %#x\n", This, dwIssueFlags, This->type); - switch (This->type) { - case WINED3DQUERYTYPE_OCCLUSION: - if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) { - WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx; + /* The fixme is printed when the app asks for the resulting data */ + WARN("(%p) : Unhandled query type %#x\n", This, This->type); - if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { - WARN("Not the owning context, can't start query\n"); - } else { - if (dwIssueFlags & WINED3DISSUE_BEGIN) { - GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId)); - checkGLcall("glBeginQuery()"); - } - if (dwIssueFlags & WINED3DISSUE_END) { - GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); - checkGLcall("glEndQuery()"); - } - } - } else { - FIXME("(%p) : Occlusion queries not supported\n", This); - } - break; - - case WINED3DQUERYTYPE_EVENT: { - if (dwIssueFlags & WINED3DISSUE_END) { - WineD3DContext *ctx = ((WineQueryEventData *)This->extendedData)->ctx; - if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { - /* GL fences can be used only from the context that created them, - * so if a different context is active, don't bother setting the query. The penalty - * of a context switch is most likely higher than the gain of a correct query result - * - * If the query is used from a different thread, don't bother creating a multithread - * context - there's no point in doing that as the query would be unusable anyway - */ - WARN("Query context not active\n"); - } else if(GL_SUPPORT(APPLE_FENCE)) { - GL_EXTCALL(glSetFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId)); - checkGLcall("glSetFenceAPPLE"); - } else if (GL_SUPPORT(NV_FENCE)) { - GL_EXTCALL(glSetFenceNV(((WineQueryEventData *)This->extendedData)->fenceId, GL_ALL_COMPLETED_NV)); - checkGLcall("glSetFenceNV"); - } - } else if(dwIssueFlags & WINED3DISSUE_BEGIN) { - /* Started implicitly at device creation */ - ERR("Event query issued with START flag - what to do?\n"); - } - } - - default: - /* The fixme is printed when the app asks for the resulting data */ - WARN("(%p) : Unhandled query type %#x\n", This, This->type); - break; + if(dwIssueFlags & WINED3DISSUE_BEGIN) { + This->state = QUERY_BUILDING; + } else { + This->state = QUERY_SIGNALLED; } return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ @@ -454,3 +533,33 @@ const IWineD3DQueryVtbl IWineD3DQuery_Vtbl = IWineD3DQueryImpl_GetType, IWineD3DQueryImpl_Issue }; + +const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl = +{ + /*** IUnknown methods ***/ + IWineD3DQueryImpl_QueryInterface, + IWineD3DQueryImpl_AddRef, + IWineD3DQueryImpl_Release, + /*** IWineD3Dquery methods ***/ + IWineD3DQueryImpl_GetParent, + IWineD3DQueryImpl_GetDevice, + IWineD3DEventQueryImpl_GetData, + IWineD3DEventQueryImpl_GetDataSize, + IWineD3DQueryImpl_GetType, + IWineD3DEventQueryImpl_Issue +}; + +const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl = +{ + /*** IUnknown methods ***/ + IWineD3DQueryImpl_QueryInterface, + IWineD3DQueryImpl_AddRef, + IWineD3DQueryImpl_Release, + /*** IWineD3Dquery methods ***/ + IWineD3DQueryImpl_GetParent, + IWineD3DQueryImpl_GetDevice, + IWineD3DOcclusionQueryImpl_GetData, + IWineD3DOcclusionQueryImpl_GetDataSize, + IWineD3DQueryImpl_GetType, + IWineD3DOcclusionQueryImpl_Issue +}; diff --git a/reactos/dll/directx/wine/wined3d/resource.c b/reactos/dll/directx/wine/wined3d/resource.c index 151af2c2838..17e540bb208 100644 --- a/reactos/dll/directx/wine/wined3d/resource.c +++ b/reactos/dll/directx/wine/wined3d/resource.c @@ -88,11 +88,11 @@ void IWineD3DResourceImpl_CleanUp(IWineD3DResource *iface){ if (This->resource.wineD3DDevice != NULL) { IWineD3DDevice_ResourceReleased((IWineD3DDevice *)This->resource.wineD3DDevice, iface); - }/* NOTE: this is not really an error for systemmem resoruces */ + }/* NOTE: this is not really an error for system memory resources */ return; } -/* IWineD3DResource Interface follow: */ +/* IWineD3DResource Interface follows: */ HRESULT WINAPI IWineD3DResourceImpl_GetDevice(IWineD3DResource *iface, IWineD3DDevice** ppDevice) { IWineD3DResourceImpl *This = (IWineD3DResourceImpl *)iface; TRACE("(%p) : returning %p\n", This, This->resource.wineD3DDevice); @@ -235,6 +235,11 @@ void WINAPI IWineD3DResourceImpl_PreLoad(IWineD3DResource *iface) { FIXME("(%p) : stub\n", This); } +void WINAPI IWineD3DResourceImpl_UnLoad(IWineD3DResource *iface) { + IWineD3DResourceImpl *This = (IWineD3DResourceImpl *)iface; + FIXME("(%p) : stub\n", This); +} + WINED3DRESOURCETYPE WINAPI IWineD3DResourceImpl_GetType(IWineD3DResource *iface) { IWineD3DResourceImpl *This = (IWineD3DResourceImpl *)iface; TRACE("(%p) : returning %d\n", This, This->resource.resourceType); @@ -271,5 +276,6 @@ static const IWineD3DResourceVtbl IWineD3DResource_Vtbl = IWineD3DResourceImpl_SetPriority, IWineD3DResourceImpl_GetPriority, IWineD3DResourceImpl_PreLoad, + IWineD3DResourceImpl_UnLoad, IWineD3DResourceImpl_GetType }; diff --git a/reactos/dll/directx/wine/wined3d/state.c b/reactos/dll/directx/wine/wined3d/state.c index d5bf9924daf..77b7a86e868 100644 --- a/reactos/dll/directx/wine/wined3d/state.c +++ b/reactos/dll/directx/wine/wined3d/state.c @@ -1,3 +1,4 @@ + /* * Direct3D state management * @@ -7,7 +8,7 @@ * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber * Copyright 2006 Henri Verbeet - * Copyright 2006-2007 Stefan Dösinger for CodeWeavers + * Copyright 2006-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,6 +37,8 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); + static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *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 @@ -83,8 +86,8 @@ static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine /* Lighting is not enabled if transformed vertices are drawn * but lighting does not affect the stream sources, so it is not grouped for performance reasons. - * This state reads the decoded vertex decl, so if it is dirty don't do anything. The - * vertex declaration appplying function calls this function for updating + * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The + * vertex declaration applying function calls this function for updating */ if(isStateDirty(context, STATE_VDECL)) { @@ -234,13 +237,26 @@ static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { int srcBlend = GL_ZERO; int dstBlend = GL_ZERO; + const StaticPixelFormatDesc *rtFormat; + IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */ if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] || stateblock->renderState[WINED3DRS_EDGEANTIALIAS] || stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) { - glEnable(GL_BLEND); - checkGLcall("glEnable GL_BLEND"); + const GlPixelFormatDesc *glDesc; + getFormatDescEntry(target->resource.format, &GLINFO_LOCATION, &glDesc); + + /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty. + * The d3d9 visual test confirms the behavior. */ + if(!(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) { + glDisable(GL_BLEND); + checkGLcall("glDisable GL_BLEND"); + return; + } else { + glEnable(GL_BLEND); + checkGLcall("glEnable GL_BLEND"); + } } else { glDisable(GL_BLEND); checkGLcall("glDisable GL_BLEND"); @@ -255,11 +271,23 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break; case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break; case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break; - case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break; - case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break; case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break; case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break; + /* To compensate the lack of format switching with backbuffer offscreen rendering, + * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA + * if the render target doesn't support alpha blending. A nonexistent alpha channel + * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO + */ + case WINED3DBLEND_DESTALPHA : + rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL); + dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE; + break; + case WINED3DBLEND_INVDESTALPHA : + rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL); + dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO; + break; + case WINED3DBLEND_SRCALPHASAT : dstBlend = GL_SRC_ALPHA_SATURATE; WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n"); @@ -291,12 +319,19 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break; case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break; case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break; - case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break; - case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break; case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break; case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break; case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break; + case WINED3DBLEND_DESTALPHA : + rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL); + srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE; + break; + case WINED3DBLEND_INVDESTALPHA : + rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL); + srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO; + break; + case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA; dstBlend = GL_ONE_MINUS_SRC_ALPHA; break; @@ -311,7 +346,6 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]); } - if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] || stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) { glEnable(GL_LINE_SMOOTH); @@ -327,9 +361,99 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D checkGLcall("glDisable(GL_LINE_SMOOTH)"); } - TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend); - glBlendFunc(srcBlend, dstBlend); - checkGLcall("glBlendFunc"); + /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */ + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) { + state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context); + } + + if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) { + int srcBlendAlpha = GL_ZERO; + int dstBlendAlpha = GL_ZERO; + + /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */ + if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) { + WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n"); + return; + } + + switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) { + case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break; + case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break; + case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break; + case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break; + case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break; + case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break; + case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break; + case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break; + case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break; + case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break; + case WINED3DBLEND_SRCALPHASAT : + dstBlend = GL_SRC_ALPHA_SATURATE; + WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n"); + break; + /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending + * values which are still valid up to d3d9. They should not occur as dest blend values + */ + case WINED3DBLEND_BOTHSRCALPHA : + dstBlendAlpha = GL_SRC_ALPHA; + srcBlendAlpha = GL_SRC_ALPHA; + FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n"); + break; + case WINED3DBLEND_BOTHINVSRCALPHA : + dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n"); + break; + case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break; + case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break; + default: + FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]); + } + + switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) { + case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break; + case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break; + case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break; + case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break; + case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break; + case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break; + case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break; + case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break; + case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break; + case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break; + case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break; + case WINED3DBLEND_BOTHSRCALPHA : + srcBlendAlpha = GL_SRC_ALPHA; + dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + break; + case WINED3DBLEND_BOTHINVSRCALPHA : + srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + dstBlendAlpha = GL_SRC_ALPHA; + break; + case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break; + case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break; + default: + FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]); + } + + GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha)); + checkGLcall("glBlendFuncSeparateEXT"); + } else { + TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend); + glBlendFunc(srcBlend, dstBlend); + checkGLcall("glBlendFunc"); + } + + /* 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->wineD3DDevice->StateTable; + StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); + } +} + +static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n"); } static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { @@ -354,7 +478,9 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha * in case it finds some texture+colorkeyenable combination which needs extra care. */ - if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) { + if(stateblock->textures[0] && ( + stateblock->textureDimensions[0] == GL_TEXTURE_2D || + stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0]; if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) { @@ -370,6 +496,7 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } if(enable_ckey || context->last_was_ckey) { + const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable; StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); } context->last_was_ckey = enable_ckey; @@ -407,7 +534,7 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine if (use_vs(stateblock->wineD3DDevice)) { /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't, * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some - * contitions I got sick of tracking down. The shader state handler disables all clip planes because + * conditions I got sick of tracking down. The shader state handler disables all clip planes because * of that - don't do anything here and keep them disabled */ if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) { @@ -467,27 +594,49 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - int glParm = GL_FUNC_ADD; +static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + WARN("Unsupported in local OpenGL implementation: glBlendEquation\n"); +} - if(!GL_SUPPORT(EXT_BLEND_MINMAX)) { - WARN("Unsupported in local OpenGL implementation: glBlendEquation\n"); +static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + 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] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) { + WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n"); return; } switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) { - case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break; - case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break; - case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break; - case WINED3DBLENDOP_MIN : glParm = GL_MIN; break; - case WINED3DBLENDOP_MAX : glParm = GL_MAX; break; + case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break; + case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break; + case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break; + case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break; + case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break; default: FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]); } - TRACE("glBlendEquation(%x)\n", glParm); - GL_EXTCALL(glBlendEquationEXT(glParm)); - checkGLcall("glBlendEquation"); + switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) { + case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break; + case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break; + case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break; + case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break; + case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break; + default: + FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]); + } + + if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) { + TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha); + GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha)); + checkGLcall("glBlendEquationSeparateEXT"); + } else { + TRACE("glBlendEquation(%x)\n", blendEquation); + GL_EXTCALL(glBlendEquationEXT(blendEquation)); + checkGLcall("glBlendEquation"); + } } static void @@ -527,18 +676,19 @@ state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular); checkGLcall("glMaterialfv"); - if(stateblock->material.Power > 128.0) { + if(stateblock->material.Power > GL_LIMITS(shininess)) { /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0 - * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp - * them, since 128 results in a hardly visible specular highlight, so it should be safe to - * to clamp to 128 + * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent + * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the + * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp + * them, it should be safe to do so without major visual distortions. */ - WARN("Material power > 128\n"); - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0); + WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess)); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess)); } else { glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power); } - checkGLcall("glMaterialf(GL_SHININESS"); + checkGLcall("glMaterialf(GL_SHININESS)"); if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { glEnable(GL_COLOR_SUM_EXT); @@ -598,55 +748,33 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, Win float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); - if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) { - /* And now the default texture color as well */ - for (i = 0; i < GL_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! - */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); - checkGLcall("glActiveTextureARB"); - } else if (i>0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - } - - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); - checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); + /* And now the default texture color as well */ + for (i = 0; i < GL_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! + */ + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); + } else if (i>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); } - } else { - GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0])); + + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); + checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); } } static void renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) { -#if 0 /* Don't use OpenGL 2.0 calls for now */ - if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) { - GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask)); - checkGLcall("glStencilFuncSeparate(...)"); - GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass)); - checkGLcall("glStencilOpSeparate(...)"); - } - else -#endif - if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) { - glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); - checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); - GL_EXTCALL(glActiveStencilFaceEXT(face)); - checkGLcall("glActiveStencilFaceEXT(...)"); - glStencilFunc(func, ref, mask); - checkGLcall("glStencilFunc(...)"); - glStencilOp(stencilFail, depthFail, stencilPass); - checkGLcall("glStencilOp(...)"); - } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) { - GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask)); - checkGLcall("glStencilFuncSeparateATI(...)"); - GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass)); - checkGLcall("glStencilOpSeparateATI(...)"); - } else { - ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n"); - } + glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); + checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); + GL_EXTCALL(glActiveStencilFaceEXT(face)); + checkGLcall("glActiveStencilFaceEXT(...)"); + glStencilFunc(func, ref, mask); + checkGLcall("glStencilFunc(...)"); + glStencilOp(stencilFail, depthFail, stencilPass); + checkGLcall("glStencilOp(...)"); } static void @@ -697,20 +825,36 @@ state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *c glEnable(GL_STENCIL_TEST); checkGLcall("glEnable GL_STENCIL_TEST"); - /* Apply back first, then front. This function calls glActiveStencilFaceEXT, - * which has an effect on the code below too. If we apply the front face - * afterwards, we are sure that the active stencil face is set to front, - * and other stencil functions which do not use two sided stencil do not have - * to set it back - */ - renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw); - renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass); + if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) { + /* Apply back first, then front. This function calls glActiveStencilFaceEXT, + * which has an effect on the code below too. If we apply the front face + * afterwards, we are sure that the active stencil face is set to front, + * and other stencil functions which do not use two sided stencil do not have + * to set it back + */ + renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, + stencilFail_ccw, depthFail_ccw, stencilPass_ccw); + renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, + stencilFail, depthFail, stencilPass); + } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) { + GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask)); + checkGLcall("glStencilFuncSeparateATI(...)"); + GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass)); + checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)"); + GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw)); + checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)"); + } else { + ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n"); + } } else if(onesided_enable) { if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) { glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); } + /* This code disables the ATI extension as well, since the standard stencil functions are equal + * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter + */ glEnable(GL_STENCIL_TEST); checkGLcall("glEnable GL_STENCIL_TEST"); glStencilFunc(func, ref, mask); @@ -723,6 +867,24 @@ state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *c } } +static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD mask; + + if(stateblock->wineD3DDevice->stencilBufferTarget) { + mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK]; + } else { + mask = 0; + } + + GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); + checkGLcall("glActiveStencilFaceEXT(GL_BACK)"); + glStencilMask(mask); + checkGLcall("glStencilMask"); + GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT)); + checkGLcall("glActiveStencilFaceEXT(GL_FRONT)"); + glStencilMask(mask); +} + static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD mask; @@ -732,22 +894,11 @@ static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, mask = 0; } - if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) { - GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); - checkGLcall("glActiveStencilFaceEXT(GL_BACK)"); - glStencilMask(mask); - checkGLcall("glStencilMask"); - GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT)); - checkGLcall("glActiveStencilFaceEXT(GL_FRONT)"); - glStencilMask(mask); - } else { - glStencilMask(mask); - } + glStencilMask(mask); checkGLcall("glStencilMask"); } static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - /* TODO: Put this into the vertex type block once that is in the state table */ BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE]; BOOL is_ps3 = use_ps(stateblock->wineD3DDevice) && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0); @@ -769,9 +920,9 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo * -1/(e-s) and e/(e-s) respectively. */ glFogf(GL_FOG_START, 0.0f); - checkGLcall("glFogf(GL_FOG_START, fogstart"); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); glFogf(GL_FOG_END, 1.0f); - checkGLcall("glFogf(GL_FOG_END, fogend"); + checkGLcall("glFogf(GL_FOG_END, fogend)"); } return; } @@ -840,7 +991,7 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } context->last_was_foggy_shader = TRUE; @@ -881,7 +1032,7 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } } @@ -898,10 +1049,10 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo case WINED3DFOG_EXP: { if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_EXP); - checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; @@ -910,10 +1061,10 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo case WINED3DFOG_EXP2: { if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_EXP2); - checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; @@ -922,10 +1073,10 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo case WINED3DFOG_LINEAR: { if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_LINEAR); - checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; @@ -939,7 +1090,7 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo if(GL_SUPPORT(EXT_FOG_COORD)) { if(context->fog_coord == FALSE) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)"); context->fog_coord = TRUE; } glFogi(GL_FOG_MODE, GL_LINEAR); @@ -962,30 +1113,30 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) { case WINED3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); - checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; case WINED3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); - checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; case WINED3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); - checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT"); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); context->fog_coord = FALSE; } break; @@ -1003,21 +1154,21 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo if(fogstart != fogend) { glFogfv(GL_FOG_START, &fogstart); - checkGLcall("glFogf(GL_FOG_START, fogstart"); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); TRACE("Fog Start == %f\n", fogstart); glFogfv(GL_FOG_END, &fogend); - checkGLcall("glFogf(GL_FOG_END, fogend"); + checkGLcall("glFogf(GL_FOG_END, fogend)"); TRACE("Fog End == %f\n", fogend); } else { glFogf(GL_FOG_START, -1.0 / 0.0); - checkGLcall("glFogf(GL_FOG_START, fogstart"); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); TRACE("Fog Start == %f\n", fogstart); glFogf(GL_FOG_END, 0.0); - checkGLcall("glFogf(GL_FOG_END, fogend"); + checkGLcall("glFogf(GL_FOG_END, fogend)"); TRACE("Fog End == %f\n", fogend); } } else { @@ -1029,26 +1180,26 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo * -1/(e-s) and e/(e-s) respectively. */ glFogf(GL_FOG_START, 0.0f); - checkGLcall("glFogf(GL_FOG_START, fogstart"); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); glFogf(GL_FOG_END, 1.0f); - checkGLcall("glFogf(GL_FOG_END, fogend"); + checkGLcall("glFogf(GL_FOG_END, fogend)"); } } } +static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) { + WARN("Range fog enabled, but not supported by this opengl implementation\n"); + } +} + static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) { - if (GL_SUPPORT(NV_FOG_DISTANCE)) { - glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); - checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)"); - } else { - WARN("Range fog enabled, but not supported by this opengl implementation\n"); - } + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); + checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)"); } else { - if (GL_SUPPORT(NV_FOG_DISTANCE)) { - glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); - checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)"); - } + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); + checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)"); } } @@ -1071,7 +1222,7 @@ static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi /* TODO: Merge with primitive type + init_materials()!! */ static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; GLenum Parm = 0; WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse; BOOL isDiffuseSupplied; @@ -1249,40 +1400,70 @@ static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { union { DWORD d; float f; } tmpvalue; tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN]; - if(GL_SUPPORT(ARB_POINT_PARAMETERS)) { - GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f); - checkGLcall("glPointParameterfARB(..."); - } - else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) { - GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f); - checkGLcall("glPointParameterfEXT(...);"); - } else if(tmpvalue.f != 1.0) { + if(tmpvalue.f != 1.0) { FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f); } } -static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + union { + DWORD d; + float f; + } tmpvalue; + + tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN]; + GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f); + checkGLcall("glPointParameterfEXT(...)"); +} + +static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + union { + DWORD d; + float f; + } tmpvalue; + + tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN]; + GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f); + checkGLcall("glPointParameterfARB(...)"); +} + +static void state_psizemax_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { union { DWORD d; float f; } tmpvalue; tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX]; - if(GL_SUPPORT(ARB_POINT_PARAMETERS)) { - GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f); - checkGLcall("glPointParameterfARB(..."); - } - else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) { - GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f); - checkGLcall("glPointParameterfEXT(...);"); - } else if(tmpvalue.f != 64.0) { + GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f); + checkGLcall("glPointParameterfARB(...)"); +} + +static void state_psizemax_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + union { + DWORD d; + float f; + } tmpvalue; + + tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX]; + GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f); + checkGLcall("glPointParameterfEXT(...)"); +} + +static void state_psizemax_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + union { + DWORD d; + float f; + } tmpvalue; + + tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX]; + if(tmpvalue.f != 64.0) { FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f); } } @@ -1293,8 +1474,6 @@ static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3 * POINTSCALEENABLE controls how point size value is treated. If set to * true, the point size is scaled with respect to height of viewport. * When set to false point size is in pixels. - * - * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp */ /* Default values */ @@ -1346,11 +1525,11 @@ static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att); - checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ..."); + checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)"); } else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att); - checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ..."); + checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)"); } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) { WARN("POINT_PARAMETERS not supported in this version of opengl\n"); } @@ -1408,28 +1587,28 @@ static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { /* TODO: NV_POINT_SPRITE */ - if (!GL_SUPPORT(ARB_POINT_SPRITE)) { + if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) { TRACE("Point sprites not supported\n"); - return; } +} +static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) { glEnable(GL_POINT_SPRITE_ARB); - checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n"); + checkGLcall("glEnable(GL_POINT_SPRITE_ARB)"); } else { glDisable(GL_POINT_SPRITE_ARB); - checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n"); + checkGLcall("glDisable(GL_POINT_SPRITE_ARB)"); } } static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { /** http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/ - http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp - Descussion that ways to turn on WRAPing to solve an opengl conversion problem. + Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem. http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248 so far as I can tell, wrapping and texture-coordinate generate go hand in hand, @@ -1455,19 +1634,19 @@ static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } } -static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - if( GL_SUPPORT(ARB_MULTISAMPLE) ) { - if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { - glEnable(GL_MULTISAMPLE_ARB); - checkGLcall("glEnable(GL_MULTISAMPLE_ARB)"); - } else { - glDisable(GL_MULTISAMPLE_ARB); - checkGLcall("glDisable(GL_MULTISAMPLE_ARB)"); - } +static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { + WARN("Multisample antialiasing not supported by gl\n"); + } +} + +static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { + glEnable(GL_MULTISAMPLE_ARB); + checkGLcall("glEnable(GL_MULTISAMPLE_ARB)"); } else { - if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { - WARN("Multisample antialiasing not supported by gl\n"); - } + glDisable(GL_MULTISAMPLE_ARB); + checkGLcall("glDisable(GL_MULTISAMPLE_ARB)"); } } @@ -1572,12 +1751,6 @@ static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]); } -static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - TRACE("Stub\n"); - if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) - FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]); -} - static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { if(stateblock->renderState[WINED3DRS_WRAPU]) { FIXME("Render state WINED3DRS_WRAPU not implemented yet\n"); @@ -1668,81 +1841,1115 @@ static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -/* Activates the texture dimension according to the bound D3D texture. - * Does not care for the colorop or correct gl texture unit(when using nvrc) - * Requires the caller to activate the correct unit before - */ -static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - BOOL bumpmap = FALSE; +/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/ +#if defined (GL_VERSION_1_3) +# define useext(A) A +#elif defined (GL_EXT_texture_env_combine) +# define useext(A) A##_EXT +#elif defined (GL_ARB_texture_env_combine) +# define useext(A) A##_ARB +#endif - if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE || - stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) { - bumpmap = TRUE; - context->texShaderBumpMap |= (1 << stage); +static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) { + /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the + * input should be used for all input components. The WINED3DTA_COMPLEMENT + * flag specifies the complement of the input should be used. */ + BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE; + BOOL complement = arg & WINED3DTA_COMPLEMENT; + + /* Calculate the operand */ + if (complement) { + if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA; + else *operand = GL_ONE_MINUS_SRC_COLOR; } else { - context->texShaderBumpMap &= ~(1 << stage); + if (from_alpha) *operand = GL_SRC_ALPHA; + else *operand = GL_SRC_COLOR; } - if(stateblock->textures[stage]) { - switch(stateblock->textureDimensions[stage]) { - case GL_TEXTURE_2D: - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D); - } else { - glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable(GL_TEXTURE_3D)"); - if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { - glDisable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); - } - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable(GL_TEXTURE_2D)"); - } - break; - case GL_TEXTURE_3D: - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D); - } else { - if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { - glDisable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); - } - glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable(GL_TEXTURE_2D)"); - glEnable(GL_TEXTURE_3D); - checkGLcall("glEnable(GL_TEXTURE_3D)"); - } - break; - case GL_TEXTURE_CUBE_MAP_ARB: - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB); - } else { - glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable(GL_TEXTURE_2D)"); - glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable(GL_TEXTURE_3D)"); - glEnable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)"); - } - break; - } - } else { - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE); - } else { - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable(GL_TEXTURE_2D)"); - glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable(GL_TEXTURE_3D)"); - if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { - glDisable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); - } - /* Binding textures is done by samplers. A dummy texture will be bound */ - } + /* Calculate the source */ + switch (arg & WINED3DTA_SELECTMASK) { + case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break; + case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break; + case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break; + case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break; + case WINED3DTA_SPECULAR: + /* + * According to the GL_ARB_texture_env_combine specs, SPECULAR is + * 'Secondary color' and isn't supported until base GL supports it + * There is no concept of temp registers as far as I can tell + */ + FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n"); + *source = GL_TEXTURE; + break; + default: + FIXME("Unrecognized texture arg %#x\n", arg); + *source = GL_TEXTURE; + break; } } +/* Setup the texture operations texture stage states */ +static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) +{ + GLenum src1, src2, src3; + GLenum opr1, opr2, opr3; + GLenum comb_target; + GLenum src0_target, src1_target, src2_target; + GLenum opr0_target, opr1_target, opr2_target; + GLenum scal_target; + GLenum opr=0, invopr, src3_target, opr3_target; + BOOL Handled = FALSE; + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */ + + TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3); + + /* This is called by a state handler which has the gl lock held and a context for the thread */ + + /* Note: Operations usually involve two ars, src0 and src1 and are operations of + the form (a1 a2). However, some of the more complex operations + take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added + in a third parameter called a0. Therefore these are operations of the form + a0 a1 a2, i.e., the new parameter goes to the front. + + However, below we treat the new (a0) parameter as src2/opr2, so in the actual + functions below, expect their syntax to differ slightly to those listed in the + manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2 + This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */ + + if (isAlpha) { + comb_target = useext(GL_COMBINE_ALPHA); + src0_target = useext(GL_SOURCE0_ALPHA); + src1_target = useext(GL_SOURCE1_ALPHA); + src2_target = useext(GL_SOURCE2_ALPHA); + opr0_target = useext(GL_OPERAND0_ALPHA); + opr1_target = useext(GL_OPERAND1_ALPHA); + opr2_target = useext(GL_OPERAND2_ALPHA); + scal_target = GL_ALPHA_SCALE; + } + else { + comb_target = useext(GL_COMBINE_RGB); + src0_target = useext(GL_SOURCE0_RGB); + src1_target = useext(GL_SOURCE1_RGB); + src2_target = useext(GL_SOURCE2_RGB); + opr0_target = useext(GL_OPERAND0_RGB); + opr1_target = useext(GL_OPERAND1_RGB); + opr2_target = useext(GL_OPERAND2_RGB); + scal_target = useext(GL_RGB_SCALE); + } + + /* If a texture stage references an invalid texture unit the stage just + * passes through the result from the previous stage */ + if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) { + arg1 = WINED3DTA_CURRENT; + op = WINED3DTOP_SELECTARG1; + } + + /* From MSDN (WINED3DTSS_ALPHAARG1) : + The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage, + then the default argument is WINED3DTA_DIFFUSE. + FIXME? If texture added/removed, may need to reset back as well? */ + if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) { + get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1); + } else { + get_src_and_opr(arg1, isAlpha, &src1, &opr1); + } + get_src_and_opr(arg2, isAlpha, &src2, &opr2); + get_src_and_opr(arg3, isAlpha, &src3, &opr3); + + TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3); + + Handled = TRUE; /* Assume will be handled */ + + /* Other texture operations require special extensions: */ + if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { + if (isAlpha) { + opr = GL_SRC_ALPHA; + invopr = GL_ONE_MINUS_SRC_ALPHA; + src3_target = GL_SOURCE3_ALPHA_NV; + opr3_target = GL_OPERAND3_ALPHA_NV; + } else { + opr = GL_SRC_COLOR; + invopr = GL_ONE_MINUS_SRC_COLOR; + src3_target = GL_SOURCE3_RGB_NV; + opr3_target = GL_OPERAND3_RGB_NV; + } + switch (op) { + case WINED3DTOP_DISABLE: /* Only for alpha */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + break; + case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */ + case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + if (op == WINED3DTOP_SELECTARG1) { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + } else { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); + } + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + break; + + case WINED3DTOP_MODULATE: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_MODULATE4X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); + checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); + break; + + case WINED3DTOP_ADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_ADDSIGNED: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_ADDSIGNED2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + + case WINED3DTOP_ADDSMOOTH: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_BLENDDIFFUSEALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDFACTORALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHAPM: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */ + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */ + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */ + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */ + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MULTIPLYADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src2); + checkGLcall("GL_TEXTURE_ENV, src3_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_BUMPENVMAP: + { + } + + case WINED3DTOP_BUMPENVMAPLUMINANCE: + FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n"); + + default: + Handled = FALSE; + } + if (Handled) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); + checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV"); + + return; + } + } /* GL_NV_texture_env_combine4 */ + + Handled = TRUE; /* Again, assume handled */ + switch (op) { + case WINED3DTOP_DISABLE: /* Only for alpha */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); + checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_SELECTARG1: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_SELECTARG2: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_MODULATE4X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); + checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); + break; + case WINED3DTOP_ADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSIGNED: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSIGNED2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_SUBTRACT: + if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else { + FIXME("This version of opengl does not support GL_SUBTRACT\n"); + } + break; + + case WINED3DTOP_BLENDDIFFUSEALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDFACTORALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDCURRENTALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_DOTPRODUCT3: + if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB"); + } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT"); + } else { + FIXME("This version of opengl does not support GL_DOT3\n"); + } + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_LERP: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src3); + checkGLcall("GL_TEXTURE_ENV, src2_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSMOOTH: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_BLENDTEXTUREALPHAPM: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MULTIPLYADD: + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src3); + checkGLcall("GL_TEXTURE_ENV, src1_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_BUMPENVMAPLUMINANCE: + if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { + /* Some apps use BUMPENVMAPLUMINANCE instead of D3DTOP_BUMPENVMAP, although + * they check for the non-luminance cap flag. Well, give them what they asked + * for :-) + */ + WARN("Application uses WINED3DTOP_BUMPENVMAPLUMINANCE\n"); + } else { + Handled = FALSE; + break; + } + /* Fall through */ + case WINED3DTOP_BUMPENVMAP: + if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { + TRACE("Using ati bumpmap on stage %d, target %d\n", Stage, Stage + 1); + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI); + checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI)"); + glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1); + checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); + checkGLcall("GL_TEXTURE_ENV, src0_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + + Handled = TRUE; + break; + } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { + /* Technically texture shader support without register combiners is possible, but not expected to occur + * on real world cards, so for now a fixme should be enough + */ + FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n"); + } + default: + Handled = FALSE; + } + + if (Handled) { + BOOL combineOK = TRUE; + if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { + DWORD op2; + + if (isAlpha) { + op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP]; + } else { + op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP]; + } + + /* Note: If COMBINE4 in effect can't go back to combine! */ + switch (op2) { + case WINED3DTOP_ADDSMOOTH: + case WINED3DTOP_BLENDTEXTUREALPHAPM: + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + case WINED3DTOP_MULTIPLYADD: + /* Ignore those implemented in both cases */ + switch (op) { + case WINED3DTOP_SELECTARG1: + case WINED3DTOP_SELECTARG2: + combineOK = FALSE; + Handled = FALSE; + break; + default: + FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha); + return; + } + } + } + + if (combineOK) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); + checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); + + return; + } + } + + /* After all the extensions, if still unhandled, report fixme */ + FIXME("Unhandled texture operation %s\n", debug_d3dtop(op)); +} + + static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; @@ -1772,14 +2979,6 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - if(stateblock->lowest_disabled_stage > 0) { - glEnable(GL_REGISTER_COMBINERS_NV); - GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage)); - } else { - glDisable(GL_REGISTER_COMBINERS_NV); - } - } if(stage >= stateblock->lowest_disabled_stage) { TRACE("Stage disabled\n"); if (mapped_stage != -1) { @@ -1792,8 +2991,9 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D glDisable(GL_TEXTURE_CUBE_MAP_ARB); checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); } - if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) { - glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE); + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); } } /* All done */ @@ -1804,50 +3004,24 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D * if the sampler for this stage is dirty */ if(!isStateDirty(context, STATE_SAMPLER(stage))) { - if (tex_used) activate_dimensions(stage, stateblock, context); + if (tex_used) texture_activate_dimensions(stage, stateblock, context); } - /* Set the texture combiners */ - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, - stateblock->textureState[stage][WINED3DTSS_COLOROP], - stateblock->textureState[stage][WINED3DTSS_COLORARG1], - stateblock->textureState[stage][WINED3DTSS_COLORARG2], - stateblock->textureState[stage][WINED3DTSS_COLORARG0], - mapped_stage); - - /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set, - * thus the texture shader may have to be updated - */ - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE || - stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE; - BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE; - if(usesBump != usedBump) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1)); - checkGLcall("glActiveTextureARB"); - activate_dimensions(stage + 1, stateblock, context); - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); - checkGLcall("glActiveTextureARB"); - } - } - } else { - set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, - stateblock->textureState[stage][WINED3DTSS_COLOROP], - stateblock->textureState[stage][WINED3DTSS_COLORARG1], - stateblock->textureState[stage][WINED3DTSS_COLORARG2], - stateblock->textureState[stage][WINED3DTSS_COLORARG0]); - } + set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, + stateblock->textureState[stage][WINED3DTSS_COLOROP], + stateblock->textureState[stage][WINED3DTSS_COLORARG1], + stateblock->textureState[stage][WINED3DTSS_COLORARG2], + stateblock->textureState[stage][WINED3DTSS_COLORARG0]); } -static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage]; DWORD op, arg1, arg2, arg0; TRACE("Setting alpha op for stage %d\n", stage); - /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */ + /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */ if (mapped_stage != -1) { if (GL_SUPPORT(ARB_MULTITEXTURE)) { if (tex_used && mapped_stage >= GL_LIMITS(textures)) { @@ -1869,7 +3043,8 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0]; if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && - stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) { + stateblock->textures[0] && + (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; if(surf->CKeyFlags & WINEDDSD_CKSRCBLT && @@ -1880,21 +3055,50 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D * cannot remove the texture's alpha channel entirely. * * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work - * on color keyed surfaces. + * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to + * draw things like translucent text and perform other blending effects. * + * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the + * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha. + * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha + * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by + * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated + * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending, + * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha; + * otherwise, selecting diffuse alpha is ignored in favour of texture alpha. + * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing */ - if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1; - if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE; - else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE; + if(op == WINED3DTOP_DISABLE) { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_SELECTARG1; + } + else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + arg2 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg1 = WINED3DTA_TEXTURE; + } + else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg2 = WINED3DTA_TEXTURE; + } } } + /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to + * this if block here, and the other code(color keying, texture unit selection) are the same + */ TRACE("Setting alpha op for stage %d\n", stage); if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, op, arg1, arg2, arg0, - mapped_stage); + mapped_stage, + stateblock->textureState[stage][WINED3DTSS_RESULTARG]); } else { set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, op, arg1, arg2, arg0); @@ -1902,9 +3106,10 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0); + DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit]; BOOL generated; + int coordIdx; /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */ if(use_vs(stateblock->wineD3DDevice) || @@ -1913,7 +3118,7 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W return; } - if (mapped_stage < 0) return; + if (mapped_stage == -1) return; if (GL_SUPPORT(ARB_MULTITEXTURE)) { if(mapped_stage >= GL_LIMITS(textures)) { @@ -1927,14 +3132,16 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W return; } generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU; + coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1); - set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0], + set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0], stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw, - stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ? - stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType: - WINED3DDECLTYPE_UNUSED); + stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwStride ? + stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwType: + WINED3DDECLTYPE_UNUSED, + stateblock->wineD3DDevice->frag_pipe->ffp_proj_control); /* The sampler applying function calls us if this changes */ if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) { @@ -2003,6 +3210,8 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertex GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1)); } } + + checkGLcall("loadTexCoords"); } static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { @@ -2074,15 +3283,15 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n"); glEnable(GL_TEXTURE_GEN_S); - checkGLcall("glEnable(GL_TEXTURE_GEN_S);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_S)"); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)"); glEnable(GL_TEXTURE_GEN_T); - checkGLcall("glEnable(GL_TEXTURE_GEN_T);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_T)"); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)"); glEnable(GL_TEXTURE_GEN_R); - checkGLcall("glEnable(GL_TEXTURE_GEN_R);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_R)"); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)"); } @@ -2107,15 +3316,15 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine glPopMatrix(); glEnable(GL_TEXTURE_GEN_S); - checkGLcall("glEnable(GL_TEXTURE_GEN_S);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_S)"); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)"); glEnable(GL_TEXTURE_GEN_T); - checkGLcall("glEnable(GL_TEXTURE_GEN_T);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_T)"); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)"); glEnable(GL_TEXTURE_GEN_R); - checkGLcall("glEnable(GL_TEXTURE_GEN_R);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_R)"); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)"); } @@ -2141,15 +3350,15 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine glPopMatrix(); glEnable(GL_TEXTURE_GEN_S); - checkGLcall("glEnable(GL_TEXTURE_GEN_S);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_S)"); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)"); glEnable(GL_TEXTURE_GEN_T); - checkGLcall("glEnable(GL_TEXTURE_GEN_T);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_T)"); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)"); glEnable(GL_TEXTURE_GEN_R); - checkGLcall("glEnable(GL_TEXTURE_GEN_R);"); + checkGLcall("glEnable(GL_TEXTURE_GEN_R)"); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)"); } @@ -2170,7 +3379,7 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine /* Update the texture matrix */ if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) { - transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context); + transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); } if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) { @@ -2202,13 +3411,9 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; - union { - DWORD d; - float f; - } tmpvalue; if(stateblock->pixelShader && stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) { /* The pixel shader has to know the luminance scale. Do a constants update if it * isn't scheduled anyway */ @@ -2217,46 +3422,38 @@ static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, W shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); } } - - tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; - if(tmpvalue.f != 0.0) { - FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n"); - } } -static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; - union { - DWORD d; - float f; - } tmpvalue; +static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + BOOL texIsPow2 = FALSE; + DWORD sampler = state - STATE_SAMPLER(0); + IWineD3DBaseTexture *texture = stateblock->textures[sampler]; - if(stateblock->pixelShader && stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { - /* The pixel shader has to know the luminance offset. Do a constants update if it - * isn't scheduled anyway - */ - if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && - !isStateDirty(context, STATE_PIXELSHADER)) { - shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + if(!texture) return; + /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates + * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the + * scaling is reapplied or removed, the texture matrix has to be reapplied + * + * The mapped stage is alrady active because the sampler() function below, which is part of the + * misc pipeline + */ + if(sampler < MAX_TEXTURES) { + if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D || + stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) { + if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 || + ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) { + texIsPow2 = TRUE; + } + } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) { + if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) { + texIsPow2 = TRUE; + } } - } - tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; - if(tmpvalue.f != 0.0) { - FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n"); - } -} - -static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; - - if(stage >= GL_LIMITS(texture_stages)) { - return; - } - - if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) { - FIXME("WINED3DTSS_RESULTARG not supported yet\n"); + if(texIsPow2 || context->lastWasPow2Texture[sampler]) { + context->lastWasPow2Texture[sampler] = texIsPow2; + transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); + } } } @@ -2291,31 +3488,8 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } if(stateblock->textures[sampler]) { - BOOL texIsPow2 = FALSE; - - /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates - * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the - * scaling is reapplied or removed, the texture matrix has to be reapplied - */ - if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) { - if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) { - if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0 || - ((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[5] != 1.0 ) { - texIsPow2 = TRUE; - } - } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) { - if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0) { - texIsPow2 = TRUE; - } - } - - if(texIsPow2 || context->lastWasPow2Texture[sampler]) { - context->lastWasPow2Texture[sampler] = texIsPow2; - transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context); - } - } - - IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]); + IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]); + IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler]); IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]); if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) { @@ -2323,25 +3497,10 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmpvalue.f); - checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ..."); + checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)"); } - if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader && - ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) { - /* Using a pixel shader? Verify the sampler types */ - - /* Make sure that the texture dimensions are enabled. I don't have to disable the other - * dimensions because the shader knows from which texture type to sample from. For the sake of - * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused - * dimensions. This should make wrong sampling sources visible :-) - */ - glEnable(stateblock->textureDimensions[sampler]); - checkGLcall("glEnable(stateblock->textureDimensions[sampler])"); - } else if(sampler < stateblock->lowest_disabled_stage) { - if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) { - activate_dimensions(sampler, stateblock, context); - } - + if(!use_ps(stateblock->wineD3DDevice) && sampler < stateblock->lowest_disabled_stage) { if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) { /* If color keying is enabled update the alpha test, it depends on the existence * of a color key in stage 0 @@ -2349,11 +3508,14 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context); } } - } else if(sampler < GL_LIMITS(texture_stages)) { + } else if(mapped_stage < GL_LIMITS(textures)) { if(sampler < stateblock->lowest_disabled_stage) { /* TODO: What should I do with pixel shaders here ??? */ - if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) { - activate_dimensions(sampler, stateblock, context); + if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) { + /* If color keying is enabled update the alpha test, it depends on the existence + * of a color key in stage 0 + */ + state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context); } } /* Otherwise tex_colorop disables the stage */ glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]); @@ -2361,11 +3523,26 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } } -static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void apply_pshader_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + + if (use_ps(device)) { + if(!context->last_was_pshader) { + state_fog(state, stateblock, context); + } + context->last_was_pshader = TRUE; + } else { + if(context->last_was_pshader) { + state_fog(state, stateblock, context); + } + context->last_was_pshader = FALSE; + } +} + +void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL use_pshader = use_ps(device); BOOL use_vshader = use_vs(device); - BOOL update_fog = FALSE; int i; if (use_pshader) { @@ -2379,7 +3556,6 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D sampler(STATE_SAMPLER(i), stateblock, context); } } - update_fog = TRUE; } else { /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler() * if a different texture was bound. I don't have to do anything. @@ -2394,70 +3570,51 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D */ for(i=0; i < MAX_TEXTURES; i++) { if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) { - tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context); + device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply + (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context); } } - if(context->last_was_pshader) - update_fog = TRUE; } - if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) { + if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader); if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); } } - - if(update_fog) - state_fog(state, stateblock, context); - - context->last_was_pshader = use_pshader; } -static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; - if(stateblock->pixelShader && stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) { + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) { /* 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) && - !isStateDirty(context, STATE_PIXELSHADER)) { + !isStateDirty(context, STATE_PIXELSHADER)) { shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); } } +} - if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { - if(stage >= GL_LIMITS(texture_stages)) { - WARN("Bump env matrix of unsupported stage set\n"); - } else if(GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); - checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))"); - } - GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, - (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]))); - checkGLcall("glTexBumpParameterfvATI"); - } - if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to - * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump - * map offseting is done in the stage reading the bump mapped texture, and the perturbation - * 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 - */ - DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1]; - - if(mapped_stage < GL_LIMITS(textures)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); - checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))"); - - glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, - (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])); - checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n"); - } +static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + float mat[2][2]; + + if(stage >= GL_LIMITS(texture_stages)) { + WARN("Bump env matrix of unsupported stage set\n"); + } else if(GL_SUPPORT(ARB_MULTITEXTURE)) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); + checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))"); } + mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); + mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]); + mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]); + mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]); + GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, (float *) mat)); + checkGLcall("glTexBumpParameterfvATI"); } static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { @@ -2465,7 +3622,7 @@ static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, Win * * Deliberately no check if the vertex declaration is dirty because the vdecl state * does not always update the world matrix, only on a switch between transformed - * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one + * and untransformed draws. It *may* happen that the world matrix is set 2 times during one * draw, but that should be rather rare and cheaper in total. */ glMatrixMode(GL_MODELVIEW); @@ -2477,12 +3634,12 @@ static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } else { /* In the general case, the view matrix is the identity matrix */ if (stateblock->wineD3DDevice->view_ident) { - glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); checkGLcall("glLoadMatrixf"); } else { - glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); checkGLcall("glLoadMatrixf"); - glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); + glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); checkGLcall("glMultMatrixf"); } } @@ -2498,7 +3655,7 @@ static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */ glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); TRACE("Clipplane [%f,%f,%f,%f]\n", stateblock->clipplane[index][0], @@ -2550,6 +3707,25 @@ static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } +static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + static BOOL once = FALSE; + + 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; + + case WINED3DVBF_TWEENING: + WARN("Tweening not supported yet\n"); + } +} + static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND]; @@ -2557,42 +3733,29 @@ static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, W case WINED3DVBF_1WEIGHTS: case WINED3DVBF_2WEIGHTS: case WINED3DVBF_3WEIGHTS: - if(GL_SUPPORT(ARB_VERTEX_BLEND)) { - glEnable(GL_VERTEX_BLEND_ARB); - checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)"); + glEnable(GL_VERTEX_BLEND_ARB); + checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)"); - /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context - * creation with enabling GL_WEIGHT_SUM_UNITY_ARB. - */ - GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1)); + /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context + * creation with enabling GL_WEIGHT_SUM_UNITY_ARB. + */ + GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1)); - if(!stateblock->wineD3DDevice->vertexBlendUsed) { - int i; - for(i = 1; i < GL_LIMITS(blends); i++) { - if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) { - transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context); - } + if(!stateblock->wineD3DDevice->vertexBlendUsed) { + int i; + for(i = 1; i < GL_LIMITS(blends); i++) { + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) { + transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context); } - stateblock->wineD3DDevice->vertexBlendUsed = TRUE; - } - } else { - static BOOL once = FALSE; - if(!once) { - once = TRUE; - /* TODO: Implement vertex blending in drawStridedSlow */ - FIXME("Vertex blending enabled, but not supported by hardware\n"); } + stateblock->wineD3DDevice->vertexBlendUsed = TRUE; } break; case WINED3DVBF_DISABLE: case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */ - if(GL_SUPPORT(ARB_VERTEX_BLEND)) { - glDisable(GL_VERTEX_BLEND_ARB); - checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)"); - } else { - TRACE("Vertex blending disabled\n"); - } + glDisable(GL_VERTEX_BLEND_ARB); + checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)"); break; case WINED3DVBF_TWEENING: @@ -2618,7 +3781,7 @@ static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine glMatrixMode(GL_MODELVIEW); checkGLcall("glMatrixMode(GL_MODELVIEW)"); - glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); checkGLcall("glLoadMatrixf(...)"); /* Reset lights. TODO: Call light apply func */ @@ -2662,12 +3825,6 @@ static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static const GLfloat invymat[16] = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f}; - static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { glMatrixMode(GL_PROJECTION); checkGLcall("glMatrixMode(GL_PROJECTION)"); @@ -2735,8 +3892,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock /* D3D texture coordinates are flipped compared to OpenGL ones, so * render everything upside down when rendering offscreen. */ if (stateblock->wineD3DDevice->render_offscreen) { - glMultMatrixf(invymat); - checkGLcall("glMultMatrixf(invymat)"); + glScalef(1.0, -1.0, 1.0); + checkGLcall("glScalef"); } } else { /* The rule is that the window coordinate 0 does not correspond to the @@ -2757,17 +3914,39 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock of Z buffer precision and the clear values do not match in the z test. Thus scale [0;1] to [-1;1], so when gl undoes that we utilize the full z range */ - glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0); - checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)"); - glScalef(1.0, 1.0, 2.0); - /* D3D texture coordinates are flipped compared to OpenGL ones, so - * render everything upside down when rendering offscreen. */ + /* + * Careful with the order of operations here, we're essentially working backwards: + * x = x + 1/w; + * y = (y - 1/h) * flip; + * z = z * 2 - 1; + * + * Becomes: + * glTranslatef(0.0, 0.0, -1.0); + * glScalef(1.0, 1.0, 2.0); + * + * glScalef(1.0, flip, 1.0); + * glTranslatef(1/w, -1/h, 0.0); + * + * This is equivalent to: + * glTranslatef(1/w, -flip/h, -1.0) + * glScalef(1.0, flip, 2.0); + */ + if (stateblock->wineD3DDevice->render_offscreen) { - glMultMatrixf(invymat); - checkGLcall("glMultMatrixf(invymat)"); + /* D3D texture coordinates are flipped compared to OpenGL ones, so + * render everything upside down when rendering offscreen. */ + glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0); + checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)"); + glScalef(1.0, -1.0, 2.0); + } else { + glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0); + checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)"); + glScalef(1.0, 1.0, 2.0); } - glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]); + checkGLcall("glScalef"); + + glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]); checkGLcall("glLoadMatrixf"); } } @@ -2785,8 +3964,6 @@ static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) { } if (GL_SUPPORT(ARB_VERTEX_BLEND)) { glDisableClientState(GL_WEIGHT_ARRAY_ARB); - } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) { - glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT); } unloadTexCoords(stateblock); } @@ -2796,7 +3973,7 @@ static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) { */ static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) { /* disable any attribs (this is the same for both GLSL and ARB modes) */ - GLint maxAttribs; + GLint maxAttribs = 16; int i; /* Leave all the attribs disabled */ @@ -2806,7 +3983,15 @@ static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) { maxAttribs = 16; for (i = 0; i < maxAttribs; ++i) { GL_EXTCALL(glDisableVertexAttribArrayARB(i)); - checkGLcall("glDisableVertexAttribArrayARB(reg);"); + checkGLcall("glDisableVertexAttribArrayARB(reg)"); + /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now + * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00. + * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really + * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast + * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two. + */ + GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0)); + checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)"); } } @@ -2814,6 +3999,8 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0; int i; UINT *offset = stateblock->streamOffset; + IWineD3DVertexBufferImpl *vb; + DWORD_PTR shift_index; /* Default to no instancing */ stateblock->wineD3DDevice->instancedDraw = FALSE; @@ -2838,12 +4025,39 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi checkGLcall("glBindBufferARB"); curVBO = strided->u.input[i].VBO; } - GL_EXTCALL(glVertexAttribPointerARB(i, - WINED3D_ATR_SIZE(strided->u.input[i].dwType), - WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), - WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), - strided->u.input[i].dwStride, - strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) ); + vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo]; + /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a + * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no + * vbo we won't be load converted attributes anyway + */ + if(curVBO && vb->conv_shift) { + TRACE("Loading attribute from shifted buffer\n"); + TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride); + TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]); + TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType)); + shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]); + shift_index = shift_index % strided->u.input[i].dwStride; + GL_EXTCALL(glVertexAttribPointerARB(i, + WINED3D_ATR_SIZE(strided->u.input[i].dwType), + WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), + WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), + vb->conv_stride, + + strided->u.input[i].lpData + vb->conv_shift[shift_index] + + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + + offset[strided->u.input[i].streamNo])); + + } else { + GL_EXTCALL(glVertexAttribPointerARB(i, + WINED3D_ATR_SIZE(strided->u.input[i].dwType), + WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), + WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), + strided->u.input[i].dwStride, + + strided->u.input[i].lpData + + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + + offset[strided->u.input[i].streamNo]) ); + } GL_EXTCALL(glEnableVertexAttribArrayARB(i)); } else { /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and @@ -2851,7 +4065,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi */ BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]; if(strided->u.input[i].VBO) { - IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo]; + vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo]; ptr += (long) vb->resource.allocatedMemory; } GL_EXTCALL(glDisableVertexAttribArrayARB(i)); @@ -2931,6 +4145,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi } } } + checkGLcall("Loading numbered arrays"); } /* Used from 2 different functions, and too big to justify making it inlined */ @@ -2982,20 +4197,6 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte showfixme = FALSE; } } - } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) { - /* FIXME("TODO\n");*/ -#if 0 - - GL_EXTCALL(glVertexWeightPointerEXT)( - WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), - WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType), - sd->u.s.blendWeights.dwStride, - sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride); - checkGLcall("glVertexWeightPointerEXT(numBlends, ...)"); - glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT); - checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)"); -#endif - } else { /* TODO: support blends in drawStridedSlow * No need to write a FIXME here, this is done after the general vertex decl decoding @@ -3010,66 +4211,6 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte } } -#if 0 /* FOG ----------------------------------------------*/ - if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) { - /* TODO: fog*/ - if (GL_SUPPORT(EXT_FOG_COORD) { - glEnableClientState(GL_FOG_COORDINATE_EXT); - (GL_EXTCALL)(FogCoordPointerEXT)( - WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType), - sd->u.s.fog.dwStride, - sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride); - } else { - /* don't bother falling back to 'slow' as we don't support software FOG yet. */ - /* FIXME: fixme once */ - TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n"); - } - } else { - if (GL_SUPPRT(EXT_FOR_COORD) { - /* make sure fog is disabled */ - glDisableClientState(GL_FOG_COORDINATE_EXT); - } - } -#endif - -#if 0 /* tangents ----------------------------------------------*/ - if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO || - sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) { - /* TODO: tangents*/ - if (GL_SUPPORT(EXT_COORDINATE_FRAME) { - if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) { - glEnable(GL_TANGENT_ARRAY_EXT); - (GL_EXTCALL)(TangentPointerEXT)( - WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType), - sd->u.s.tangent.dwStride, - sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride); - } else { - glDisable(GL_TANGENT_ARRAY_EXT); - } - if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) { - glEnable(GL_BINORMAL_ARRAY_EXT); - (GL_EXTCALL)(BinormalPointerEXT)( - WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType), - sd->u.s.binormal.dwStride, - sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride); - } else{ - glDisable(GL_BINORMAL_ARRAY_EXT); - } - - } else { - /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */ - /* FIXME: fixme once */ - TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n"); - } - } else { - if (GL_SUPPORT(EXT_COORDINATE_FRAME) { - /* make sure fog is disabled */ - glDisable(GL_TANGENT_ARRAY_EXT); - glDisable(GL_BINORMAL_ARRAY_EXT); - } - } -#endif - /* Point Size ----------------------------------------------*/ if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) { @@ -3095,9 +4236,9 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord handling for rhw mode should not impact screen position whereas in GL it does. - This may result in very slightly distored textures in rhw mode, but - a very minimal different. There's always the other option of - fixing the view matrix to prevent w from having any effect + This may result in very slightly distorted textures in rhw mode. + There's always the other option of fixing the view matrix to + prevent w from having any effect. This only applies to user pointer sources, in VBOs the vertices are fixed up */ @@ -3144,9 +4285,9 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte /* WARNING: Data here MUST be in RGBA format, so cannot */ /* go directly into fast mode from app pgm, because */ /* directx requires data in BGRA format. */ - /* currently fixupVertices swizels the format, but this isn't */ - /* very practical when using VBOS */ - /* NOTE: Unless we write a vertex shader to swizel the colour */ + /* currently fixupVertices swizzles the format, but this isn't*/ + /* very practical when using VBOs */ + /* NOTE: Unless we write a vertex shader to swizzle the colour*/ /* , or the user doesn't care and wants the speed advantage */ if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) { @@ -3160,7 +4301,9 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte checkGLcall("glBindBufferARB"); curVBO = sd->u.s.diffuse.VBO; } - glColorPointer(4, GL_UNSIGNED_BYTE, + + glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType), + WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType), sd->u.s.diffuse.dwStride, sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]); checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); @@ -3185,7 +4328,8 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte checkGLcall("glBindBufferARB"); curVBO = sd->u.s.specular.VBO; } - GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, + GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType), + WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType), sd->u.s.specular.dwStride, sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]); vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)"); @@ -3244,11 +4388,19 @@ static inline void drawPrimitiveTraceDataLocations( return; } -/* Helper for vertexdeclaration() */ -static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) { +static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL fixup = FALSE; WineDirect3DVertexStridedData *dataLocations = &device->strided_streams; + BOOL useVertexShaderFunction; + + if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader && + ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) { + useVertexShaderFunction = TRUE; + } else { + useVertexShaderFunction = FALSE; + } + if(device->up_strided) { /* Note: this is a ddraw fixed-function code path */ @@ -3285,10 +4437,16 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer } if(useVertexShaderFunction) { - TRACE("Loading numbered arrays\n"); - loadNumberedArrays(stateblock, dataLocations); - device->useDrawStridedSlow = FALSE; - context->numberedArraysLoaded = TRUE; + if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) { + TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n"); + device->useDrawStridedSlow = TRUE; + context->numberedArraysLoaded = FALSE; + } else { + TRACE("Loading numbered arrays\n"); + loadNumberedArrays(stateblock, dataLocations); + device->useDrawStridedSlow = FALSE; + context->numberedArraysLoaded = TRUE; + } } else if (fixup || (dataLocations->u.s.pSize.lpData == NULL && dataLocations->u.s.diffuse.lpData == NULL && @@ -3309,8 +4467,8 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) { FIXME("Tweening is only valid with vertex shaders\n"); } - if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) { - FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n"); + if (!useVertexShaderFunction && BUFFER_OR_DATA(binormal)) { + FIXME("Binormal bump mapping is only valid with vertex shaders\n"); } if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) { FIXME("Extended attributes are only valid with vertex shaders\n"); @@ -3330,8 +4488,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software - * here simply check whether a shader was set, or the user disabled shaders */ - if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader && - ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) { + if (use_vs(device)) { useVertexShaderFunction = TRUE; if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) { @@ -3341,8 +4498,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W updateFog = TRUE; } - handleStreams(stateblock, useVertexShaderFunction, context); - transformed = device->strided_streams.u.s.position_transformed; if (transformed) useVertexShaderFunction = FALSE; @@ -3373,6 +4528,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W */ if (useVertexShaderFunction) { device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0; + device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height; } } @@ -3438,7 +4594,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W } if(wasrhw) { /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex - * shaders themselves do not need it it, but the matrices are not reapplied automatically when + * shaders themselves do not need it, but the matrices are not reapplied automatically when * switching back from vertex shaders to fixed function processing. So make sure we leave the * fixed function vertex processing states back in a sane state before switching to shaders */ @@ -3472,13 +4628,16 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W int i; for(i = 0; i < MAX_TEXTURES; i++) { if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) { - transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context); + transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); } } } } -static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + UINT width, height; + IWineD3DSurfaceImpl *target; + glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ); checkGLcall("glDepthRange"); /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering @@ -3488,15 +4647,20 @@ static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon stateblock->viewport.Y, stateblock->viewport.Width, stateblock->viewport.Height); } else { + target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; + target->get_drawable_size(target, &width, &height); + glViewport(stateblock->viewport.X, - (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)), + (height - (stateblock->viewport.Y + stateblock->viewport.Height)), stateblock->viewport.Width, stateblock->viewport.Height); } checkGLcall("glViewport"); +} +static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width; - stateblock->wineD3DDevice->posFixup[3] = -1.0 / stateblock->viewport.Height; + stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height; if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) { transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); } @@ -3519,7 +4683,7 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/ glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); /* Diffuse: */ colRGBA[0] = lightInfo->OriginalParms.Diffuse.r; @@ -3622,37 +4786,31 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { RECT *pRect = &stateblock->scissorRect; - RECT windowRect; - UINT winHeight; - - windowRect.left = 0; - windowRect.top = 0; - windowRect.right = ((IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0])->currentDesc.Width; - windowRect.bottom = ((IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height; + UINT height; + UINT width; + IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; + target->get_drawable_size(target, &width, &height); /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply * Warning2: Even in windowed mode the coords are relative to the window, not the screen */ - winHeight = windowRect.bottom - windowRect.top; - TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight, + TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height, pRect->right - pRect->left, pRect->bottom - pRect->top); if (stateblock->wineD3DDevice->render_offscreen) { glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } else { - glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); + glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); } checkGLcall("glScissor"); } static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { - if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) { - GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); - } else { - IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData; - GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo)); - } + if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) { + GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); + } else { + IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData; + GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo)); } } @@ -3666,1076 +4824,885 @@ static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo } } -const struct StateEntry StateTable[] = -{ - /* State name representative, apply function */ - { /* 0, Undefined */ 0, state_undefined }, - { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined }, - { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, - { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined }, - { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, - { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, - { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, - { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, - { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, - { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, - { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, - { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, - { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, - { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, - { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, - { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, - { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, - { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined }, - { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined }, - { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, - { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, - { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined }, - { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, - { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, - { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, - { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, - { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, - { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, - { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, - { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, - { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl }, - { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, - { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, - { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, - { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, - { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, - { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, - { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, - { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, - { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, - { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, - { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, - { /* 42, undefined */ 0, state_undefined }, - { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, - { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined }, - { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined }, - { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, - { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, - { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, - { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, - { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, - { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, - { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, - { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, - { /* 61, Undefined */ 0, state_undefined }, - { /* 62, Undefined */ 0, state_undefined }, - { /* 63, Undefined */ 0, state_undefined }, - { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined }, - { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined }, - { /* 96, Undefined */ 0, state_undefined }, - { /* 97, Undefined */ 0, state_undefined }, - { /* 98, Undefined */ 0, state_undefined }, - { /* 99, Undefined */ 0, state_undefined }, - { /*100, Undefined */ 0, state_undefined }, - { /*101, Undefined */ 0, state_undefined }, - { /*102, Undefined */ 0, state_undefined }, - { /*103, Undefined */ 0, state_undefined }, - { /*104, Undefined */ 0, state_undefined }, - { /*105, Undefined */ 0, state_undefined }, - { /*106, Undefined */ 0, state_undefined }, - { /*107, Undefined */ 0, state_undefined }, - { /*108, Undefined */ 0, state_undefined }, - { /*109, Undefined */ 0, state_undefined }, - { /*110, Undefined */ 0, state_undefined }, - { /*111, Undefined */ 0, state_undefined }, - { /*112, Undefined */ 0, state_undefined }, - { /*113, Undefined */ 0, state_undefined }, - { /*114, Undefined */ 0, state_undefined }, - { /*115, Undefined */ 0, state_undefined }, - { /*116, Undefined */ 0, state_undefined }, - { /*117, Undefined */ 0, state_undefined }, - { /*118, Undefined */ 0, state_undefined }, - { /*119, Undefined */ 0, state_undefined }, - { /*120, Undefined */ 0, state_undefined }, - { /*121, Undefined */ 0, state_undefined }, - { /*122, Undefined */ 0, state_undefined }, - { /*123, Undefined */ 0, state_undefined }, - { /*124, Undefined */ 0, state_undefined }, - { /*125, Undefined */ 0, state_undefined }, - { /*126, Undefined */ 0, state_undefined }, - { /*127, Undefined */ 0, state_undefined }, - /* Big hole ends */ - { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, - { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, - { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, - { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, - { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, - { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, - { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, - { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, - { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, - { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, - { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, - { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, - { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, - { /*149, Undefined */ 0, state_undefined }, - { /*150, Undefined */ 0, state_undefined }, - { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, - { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, - { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl }, - { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, - { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin }, - { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, - { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, - { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, - { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, - { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, - { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa }, - { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, - { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, - { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, - { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl }, - { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax }, - { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl }, - { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, - { /*169, Undefined */ 0, state_undefined }, - { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl }, - { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, - { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, - { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, - /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */ - /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */ - { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, - { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, - { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, - { /*177, undefined */ 0, state_undefined }, - { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, - { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, - { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, - { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, - { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, - { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, - { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_PIXELSHADER, pixelshader }, - { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, - { /*196, undefined */ 0, state_undefined }, - { /*197, undefined */ 0, state_undefined }, - { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, - { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend }, - { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend }, - { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend }, - { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend }, - /* Texture stage states */ - { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, - { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, - { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, - { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, - { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, - { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, +const struct StateEntryTemplate misc_state_template[] = { + { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 }, + { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 }, + { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 }, + { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 }, + { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 }, + /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and + * vshader loadings are untied from each other + */ + { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 }, + { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 }, - { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, - { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, - { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, - { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, - { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, - { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, - { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, - { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, - { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, - { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, - { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, - { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, - { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, - { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, - { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, - { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, - { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, - { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, - { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, - { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, - { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, - { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, - { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, - { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, - { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, - { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, - { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, - { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, - { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, - { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, - { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - - { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, - { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, - { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, - { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, - { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, - { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, - { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, - { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, - { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, - { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, - { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg }, - { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined }, - { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, - /* Sampler states */ - { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler }, - { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler }, - { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler }, - { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler }, - { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler }, - { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler }, - { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler }, - { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler }, - { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler }, - { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler }, - { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler }, - { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler }, - { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler }, - { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler }, - { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler }, - { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler }, - { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler }, - { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler }, - { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler }, - { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler }, - /* Pixel shader */ - { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader }, - /* Transform states follow */ - { /* 1, undefined */ 0, state_undefined }, - { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, - { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, - { /* 4, undefined */ 0, state_undefined }, - { /* 5, undefined */ 0, state_undefined }, - { /* 6, undefined */ 0, state_undefined }, - { /* 7, undefined */ 0, state_undefined }, - { /* 8, undefined */ 0, state_undefined }, - { /* 9, undefined */ 0, state_undefined }, - { /* 10, undefined */ 0, state_undefined }, - { /* 11, undefined */ 0, state_undefined }, - { /* 12, undefined */ 0, state_undefined }, - { /* 13, undefined */ 0, state_undefined }, - { /* 14, undefined */ 0, state_undefined }, - { /* 15, undefined */ 0, state_undefined }, - { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, - { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, - { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, - { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, - { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, - { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, - { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, - { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, - /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */ - { /* 24, undefined */ 0, state_undefined }, - { /* 25, undefined */ 0, state_undefined }, - { /* 26, undefined */ 0, state_undefined }, - { /* 27, undefined */ 0, state_undefined }, - { /* 28, undefined */ 0, state_undefined }, - { /* 29, undefined */ 0, state_undefined }, - { /* 30, undefined */ 0, state_undefined }, - { /* 31, undefined */ 0, state_undefined }, - { /* 32, undefined */ 0, state_undefined }, - { /* 33, undefined */ 0, state_undefined }, - { /* 34, undefined */ 0, state_undefined }, - { /* 35, undefined */ 0, state_undefined }, - { /* 36, undefined */ 0, state_undefined }, - { /* 37, undefined */ 0, state_undefined }, - { /* 38, undefined */ 0, state_undefined }, - { /* 39, undefined */ 0, state_undefined }, - { /* 40, undefined */ 0, state_undefined }, - { /* 41, undefined */ 0, state_undefined }, - { /* 42, undefined */ 0, state_undefined }, - { /* 43, undefined */ 0, state_undefined }, - { /* 44, undefined */ 0, state_undefined }, - { /* 45, undefined */ 0, state_undefined }, - { /* 46, undefined */ 0, state_undefined }, - { /* 47, undefined */ 0, state_undefined }, - { /* 48, undefined */ 0, state_undefined }, - { /* 49, undefined */ 0, state_undefined }, - { /* 50, undefined */ 0, state_undefined }, - { /* 51, undefined */ 0, state_undefined }, - { /* 52, undefined */ 0, state_undefined }, - { /* 53, undefined */ 0, state_undefined }, - { /* 54, undefined */ 0, state_undefined }, - { /* 55, undefined */ 0, state_undefined }, - { /* 56, undefined */ 0, state_undefined }, - { /* 57, undefined */ 0, state_undefined }, - { /* 58, undefined */ 0, state_undefined }, - { /* 59, undefined */ 0, state_undefined }, - { /* 60, undefined */ 0, state_undefined }, - { /* 61, undefined */ 0, state_undefined }, - { /* 62, undefined */ 0, state_undefined }, - { /* 63, undefined */ 0, state_undefined }, - { /* 64, undefined */ 0, state_undefined }, - { /* 65, undefined */ 0, state_undefined }, - { /* 66, undefined */ 0, state_undefined }, - { /* 67, undefined */ 0, state_undefined }, - { /* 68, undefined */ 0, state_undefined }, - { /* 69, undefined */ 0, state_undefined }, - { /* 70, undefined */ 0, state_undefined }, - { /* 71, undefined */ 0, state_undefined }, - { /* 72, undefined */ 0, state_undefined }, - { /* 73, undefined */ 0, state_undefined }, - { /* 74, undefined */ 0, state_undefined }, - { /* 75, undefined */ 0, state_undefined }, - { /* 76, undefined */ 0, state_undefined }, - { /* 77, undefined */ 0, state_undefined }, - { /* 78, undefined */ 0, state_undefined }, - { /* 79, undefined */ 0, state_undefined }, - { /* 80, undefined */ 0, state_undefined }, - { /* 81, undefined */ 0, state_undefined }, - { /* 82, undefined */ 0, state_undefined }, - { /* 83, undefined */ 0, state_undefined }, - { /* 84, undefined */ 0, state_undefined }, - { /* 85, undefined */ 0, state_undefined }, - { /* 86, undefined */ 0, state_undefined }, - { /* 87, undefined */ 0, state_undefined }, - { /* 88, undefined */ 0, state_undefined }, - { /* 89, undefined */ 0, state_undefined }, - { /* 90, undefined */ 0, state_undefined }, - { /* 91, undefined */ 0, state_undefined }, - { /* 92, undefined */ 0, state_undefined }, - { /* 93, undefined */ 0, state_undefined }, - { /* 94, undefined */ 0, state_undefined }, - { /* 95, undefined */ 0, state_undefined }, - { /* 96, undefined */ 0, state_undefined }, - { /* 97, undefined */ 0, state_undefined }, - { /* 98, undefined */ 0, state_undefined }, - { /* 99, undefined */ 0, state_undefined }, - { /*100, undefined */ 0, state_undefined }, - { /*101, undefined */ 0, state_undefined }, - { /*102, undefined */ 0, state_undefined }, - { /*103, undefined */ 0, state_undefined }, - { /*104, undefined */ 0, state_undefined }, - { /*105, undefined */ 0, state_undefined }, - { /*106, undefined */ 0, state_undefined }, - { /*107, undefined */ 0, state_undefined }, - { /*108, undefined */ 0, state_undefined }, - { /*109, undefined */ 0, state_undefined }, - { /*110, undefined */ 0, state_undefined }, - { /*111, undefined */ 0, state_undefined }, - { /*112, undefined */ 0, state_undefined }, - { /*113, undefined */ 0, state_undefined }, - { /*114, undefined */ 0, state_undefined }, - { /*115, undefined */ 0, state_undefined }, - { /*116, undefined */ 0, state_undefined }, - { /*117, undefined */ 0, state_undefined }, - { /*118, undefined */ 0, state_undefined }, - { /*119, undefined */ 0, state_undefined }, - { /*120, undefined */ 0, state_undefined }, - { /*121, undefined */ 0, state_undefined }, - { /*122, undefined */ 0, state_undefined }, - { /*123, undefined */ 0, state_undefined }, - { /*124, undefined */ 0, state_undefined }, - { /*125, undefined */ 0, state_undefined }, - { /*126, undefined */ 0, state_undefined }, - { /*127, undefined */ 0, state_undefined }, - { /*128, undefined */ 0, state_undefined }, - { /*129, undefined */ 0, state_undefined }, - { /*130, undefined */ 0, state_undefined }, - { /*131, undefined */ 0, state_undefined }, - { /*132, undefined */ 0, state_undefined }, - { /*133, undefined */ 0, state_undefined }, - { /*134, undefined */ 0, state_undefined }, - { /*135, undefined */ 0, state_undefined }, - { /*136, undefined */ 0, state_undefined }, - { /*137, undefined */ 0, state_undefined }, - { /*138, undefined */ 0, state_undefined }, - { /*139, undefined */ 0, state_undefined }, - { /*140, undefined */ 0, state_undefined }, - { /*141, undefined */ 0, state_undefined }, - { /*142, undefined */ 0, state_undefined }, - { /*143, undefined */ 0, state_undefined }, - { /*144, undefined */ 0, state_undefined }, - { /*145, undefined */ 0, state_undefined }, - { /*146, undefined */ 0, state_undefined }, - { /*147, undefined */ 0, state_undefined }, - { /*148, undefined */ 0, state_undefined }, - { /*149, undefined */ 0, state_undefined }, - { /*150, undefined */ 0, state_undefined }, - { /*151, undefined */ 0, state_undefined }, - { /*152, undefined */ 0, state_undefined }, - { /*153, undefined */ 0, state_undefined }, - { /*154, undefined */ 0, state_undefined }, - { /*155, undefined */ 0, state_undefined }, - { /*156, undefined */ 0, state_undefined }, - { /*157, undefined */ 0, state_undefined }, - { /*158, undefined */ 0, state_undefined }, - { /*159, undefined */ 0, state_undefined }, - { /*160, undefined */ 0, state_undefined }, - { /*161, undefined */ 0, state_undefined }, - { /*162, undefined */ 0, state_undefined }, - { /*163, undefined */ 0, state_undefined }, - { /*164, undefined */ 0, state_undefined }, - { /*165, undefined */ 0, state_undefined }, - { /*166, undefined */ 0, state_undefined }, - { /*167, undefined */ 0, state_undefined }, - { /*168, undefined */ 0, state_undefined }, - { /*169, undefined */ 0, state_undefined }, - { /*170, undefined */ 0, state_undefined }, - { /*171, undefined */ 0, state_undefined }, - { /*172, undefined */ 0, state_undefined }, - { /*173, undefined */ 0, state_undefined }, - { /*174, undefined */ 0, state_undefined }, - { /*175, undefined */ 0, state_undefined }, - { /*176, undefined */ 0, state_undefined }, - { /*177, undefined */ 0, state_undefined }, - { /*178, undefined */ 0, state_undefined }, - { /*179, undefined */ 0, state_undefined }, - { /*180, undefined */ 0, state_undefined }, - { /*181, undefined */ 0, state_undefined }, - { /*182, undefined */ 0, state_undefined }, - { /*183, undefined */ 0, state_undefined }, - { /*184, undefined */ 0, state_undefined }, - { /*185, undefined */ 0, state_undefined }, - { /*186, undefined */ 0, state_undefined }, - { /*187, undefined */ 0, state_undefined }, - { /*188, undefined */ 0, state_undefined }, - { /*189, undefined */ 0, state_undefined }, - { /*190, undefined */ 0, state_undefined }, - { /*191, undefined */ 0, state_undefined }, - { /*192, undefined */ 0, state_undefined }, - { /*193, undefined */ 0, state_undefined }, - { /*194, undefined */ 0, state_undefined }, - { /*195, undefined */ 0, state_undefined }, - { /*196, undefined */ 0, state_undefined }, - { /*197, undefined */ 0, state_undefined }, - { /*198, undefined */ 0, state_undefined }, - { /*199, undefined */ 0, state_undefined }, - { /*200, undefined */ 0, state_undefined }, - { /*201, undefined */ 0, state_undefined }, - { /*202, undefined */ 0, state_undefined }, - { /*203, undefined */ 0, state_undefined }, - { /*204, undefined */ 0, state_undefined }, - { /*205, undefined */ 0, state_undefined }, - { /*206, undefined */ 0, state_undefined }, - { /*207, undefined */ 0, state_undefined }, - { /*208, undefined */ 0, state_undefined }, - { /*209, undefined */ 0, state_undefined }, - { /*210, undefined */ 0, state_undefined }, - { /*211, undefined */ 0, state_undefined }, - { /*212, undefined */ 0, state_undefined }, - { /*213, undefined */ 0, state_undefined }, - { /*214, undefined */ 0, state_undefined }, - { /*215, undefined */ 0, state_undefined }, - { /*216, undefined */ 0, state_undefined }, - { /*217, undefined */ 0, state_undefined }, - { /*218, undefined */ 0, state_undefined }, - { /*219, undefined */ 0, state_undefined }, - { /*220, undefined */ 0, state_undefined }, - { /*221, undefined */ 0, state_undefined }, - { /*222, undefined */ 0, state_undefined }, - { /*223, undefined */ 0, state_undefined }, - { /*224, undefined */ 0, state_undefined }, - { /*225, undefined */ 0, state_undefined }, - { /*226, undefined */ 0, state_undefined }, - { /*227, undefined */ 0, state_undefined }, - { /*228, undefined */ 0, state_undefined }, - { /*229, undefined */ 0, state_undefined }, - { /*230, undefined */ 0, state_undefined }, - { /*231, undefined */ 0, state_undefined }, - { /*232, undefined */ 0, state_undefined }, - { /*233, undefined */ 0, state_undefined }, - { /*234, undefined */ 0, state_undefined }, - { /*235, undefined */ 0, state_undefined }, - { /*236, undefined */ 0, state_undefined }, - { /*237, undefined */ 0, state_undefined }, - { /*238, undefined */ 0, state_undefined }, - { /*239, undefined */ 0, state_undefined }, - { /*240, undefined */ 0, state_undefined }, - { /*241, undefined */ 0, state_undefined }, - { /*242, undefined */ 0, state_undefined }, - { /*243, undefined */ 0, state_undefined }, - { /*244, undefined */ 0, state_undefined }, - { /*245, undefined */ 0, state_undefined }, - { /*246, undefined */ 0, state_undefined }, - { /*247, undefined */ 0, state_undefined }, - { /*248, undefined */ 0, state_undefined }, - { /*249, undefined */ 0, state_undefined }, - { /*250, undefined */ 0, state_undefined }, - { /*251, undefined */ 0, state_undefined }, - { /*252, undefined */ 0, state_undefined }, - { /*253, undefined */ 0, state_undefined }, - { /*254, undefined */ 0, state_undefined }, - { /*255, undefined */ 0, state_undefined }, - /* End huge gap */ - { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world }, - { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex }, - { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex }, - { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex }, - { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex }, - { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex }, - { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex }, - { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex }, - { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex }, - { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex }, - { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex }, - { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex }, - { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex }, - { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex }, - { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex }, - { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex }, - { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex }, - { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex }, - { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex }, - { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex }, - { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex }, - { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex }, - { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex }, - { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex }, - { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex }, - { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex }, - { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex }, - { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex }, - { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex }, - { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex }, - { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex }, - { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex }, - { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex }, - { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex }, - { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex }, - { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex }, - { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex }, - { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex }, - { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex }, - { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex }, - { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex }, - { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex }, - { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex }, - { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex }, - { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex }, - { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex }, - { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex }, - { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex }, - { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex }, - { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex }, - { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex }, - { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex }, - { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex }, - { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex }, - { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex }, - { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex }, - { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex }, - { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex }, - { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex }, - { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex }, - { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex }, - { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex }, - { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex }, - { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex }, - { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex }, - { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex }, - { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex }, - { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex }, - { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex }, - { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex }, - { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex }, - { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex }, - { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex }, - { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex }, - { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex }, - { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex }, - { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex }, - { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex }, - { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex }, - { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex }, - { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex }, - { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex }, - { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex }, - { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex }, - { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex }, - { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex }, - { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex }, - { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex }, - { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex }, - { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex }, - { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex }, - { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex }, - { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex }, - { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex }, - { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex }, - { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex }, - { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex }, - { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex }, - { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex }, - { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex }, - { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, - { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, - { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, - { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, - { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, - { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, - { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, - { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, - { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, - { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, - { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, - { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, - { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, - { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, - { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, - { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, - { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, - { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, - { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, - { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, - { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, - { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, - { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, - { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, - { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, - { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, - { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, - { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, - { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, - { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, - { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, - { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, - { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, - { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, - { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, - { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, - { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, - { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, - { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, - { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, - { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, - { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, - { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, - { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, - { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, - { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, - { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, - { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, - { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, - { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, - { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, - { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, - { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, - { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, - { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, - { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, - { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, - { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, - { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, - { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, - { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, - { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, - { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, - { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, - { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, - { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, - { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, - { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, - { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, - { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, - { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, - { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, - { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, - { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, - { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, - { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, - { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, - { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, - { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, - { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, - { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, - { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, - { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, - { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, - { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, - { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, - { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, - { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, - { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, - { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, - { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, - { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, - { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, - { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, - { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, - { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, - { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, - { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, - { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, - { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, - { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, - { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, - { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, - { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, - { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, - { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, - { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, - { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, - { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, - { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, - { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, - { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, - { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, - { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, - { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, - { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, - { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, - { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, - { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, - { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, - { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, - { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, - { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, - { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, - { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, - { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, - { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, - { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, - { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, - { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, - { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, - { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, - { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, - { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, - { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, - { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, - { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, - { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, - { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, - { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, - { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, - { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, - { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, - { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, - { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, - { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, - { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, - { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, - { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, - { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, - { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, - { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, - { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, - { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, - { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, - { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, - /* Various Vertex states follow */ - { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration }, - { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer }, - { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration }, - { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration }, - { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport }, - { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant }, - { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant }, - /* Lights */ - { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light }, - { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light }, - { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light }, - { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light }, - { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light }, - { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light }, - { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light }, - { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light }, - - { /* Scissor rect */ STATE_SCISSORRECT, scissorrect }, - /* Clip planes */ - { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane }, - { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane }, - { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane }, - { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane }, - { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane }, - { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane }, - { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane }, - { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane }, - { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane }, - { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane }, - { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane }, - { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane }, - { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane }, - { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane }, - { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane }, - { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane }, - { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane }, - { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane }, - { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane }, - { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane }, - { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane }, - { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane }, - { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane }, - { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane }, - { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane }, - { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane }, - { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane }, - { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane }, - { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane }, - { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane }, - { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane }, - { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane }, - - { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, - { /* STATE_FRONTFACE */ STATE_FRONTFACE, frontface }, + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 }, + { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT }, + { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 }, + { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 }, + { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 }, + { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 }, + { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 }, + { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 }, + { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 }, + { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 }, + { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 }, + { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 }, + { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 }, + { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 }, + { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 }, + { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 }, + { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 }, + { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 }, + { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 }, + { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 }, + { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 }, + { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 }, + { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 }, + { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 }, + { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 }, + { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 }, + { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 }, + { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 }, + { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 }, + { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 }, + { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE }, + { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 }, + { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 }, + { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 }, + { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 }, + { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 }, + { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 }, + { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 }, + { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 }, + { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 }, + { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX }, + { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 }, + { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 }, + { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 }, + { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR }, + { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 }, + { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 }, + /* Samplers */ + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 }, + { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 }, + { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 }, + { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 }, + { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 }, + { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 }, + { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 }, + { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 }, + { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 }, + { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 }, + { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 }, + { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 }, + { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, }; + +const struct StateEntryTemplate ffp_vertexstate_template[] = { + { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 }, + { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 }, + { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 }, + { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 }, + /* Clip planes */ + { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 }, + { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 }, + { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 }, + { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 }, + { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 }, + { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 }, + { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 }, + { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 }, + { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 }, + { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 }, + { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 }, + { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 }, + { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 }, + { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 }, + { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 }, + { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 }, + { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 }, + { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 }, + { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 }, + { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 }, + { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 }, + { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 }, + { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 }, + { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 }, + { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 }, + { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 }, + { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 }, + { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 }, + { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 }, + { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 }, + { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 }, + { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 }, + /* Lights */ + { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 }, + { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 }, + { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 }, + { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 }, + { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 }, + { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 }, + { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 }, + { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 }, + /* Viewport */ + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 }, + /* Transform states follow */ + { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 }, + { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, 0 }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, 0 }, + { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, + /* Fog */ + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 }, + { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 }, + { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE }, + { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 }, + { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 }, + { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 }, + { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 }, + { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 }, + { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 }, + { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 }, + { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 }, + { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 }, + { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 }, + { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 }, + { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 }, + { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND }, + { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 }, + { 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 }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, + { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_arb }, ARB_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_ext }, EXT_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_w }, 0 }, + /* pixel shaders need a different fog input */ + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pshader_fog }, 0 }, + /* 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 + */ + { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 }, + { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; + +static const struct StateEntryTemplate ffp_fragmentstate_template[] = { + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 }, + { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 }, + { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION (*gl_info) +static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { } + +static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) { + pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | + WINED3DTEXOPCAPS_ADDSIGNED | + WINED3DTEXOPCAPS_ADDSIGNED2X | + WINED3DTEXOPCAPS_MODULATE | + WINED3DTEXOPCAPS_MODULATE2X | + WINED3DTEXOPCAPS_MODULATE4X | + WINED3DTEXOPCAPS_SELECTARG1 | + WINED3DTEXOPCAPS_SELECTARG2 | + WINED3DTEXOPCAPS_DISABLE; + + if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) || + GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) || + GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | + WINED3DTEXOPCAPS_BLENDFACTORALPHA | + WINED3DTEXOPCAPS_BLENDCURRENTALPHA | + WINED3DTEXOPCAPS_LERP | + WINED3DTEXOPCAPS_SUBTRACT; + } + if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) || + GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH | + WINED3DTEXOPCAPS_MULTIPLYADD | + WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM; + } + if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3; + + if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { + pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP; + } + + pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages); + pCaps->MaxSimultaneousTextures = GL_LIMITS(textures); +} + +static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +static void ffp_fragment_free(IWineD3DDevice *iface) {} +static BOOL ffp_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking shader format support for format %s: [FAILED]\n", debug_d3dformat(fmt)); + return FALSE; +} + +const struct fragment_pipeline ffp_fragment_pipeline = { + ffp_enable, + ffp_fragment_get_caps, + ffp_fragment_alloc, + ffp_fragment_free, + ffp_conv_supported, + ffp_fragmentstate_template, + FALSE /* we cannot disable projected textures. The vertex pipe has to do it */ +}; + +static int num_handlers(APPLYSTATEFUNC *funcs) { + unsigned int i; + for(i = 0; funcs[i]; i++); + return i; +} + +static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context); + stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context); +} + +static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context); + stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context); + stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context); +} + +void compile_state_table(struct StateEntry *StateTable, + APPLYSTATEFUNC **dev_multistate_funcs, + WineD3D_GL_Info *gl_info, + const struct StateEntryTemplate *vertex, + const struct fragment_pipeline *fragment, + const struct StateEntryTemplate *misc) { + unsigned int i, type, handlers; + APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3]; + const struct StateEntryTemplate *cur; + BOOL set[STATE_HIGHEST + 1]; + + memset(multistate_funcs, 0, sizeof(multistate_funcs)); + + for(i = 0; i < STATE_HIGHEST + 1; i++) { + StateTable[i].representative = 0; + StateTable[i].apply = state_undefined; + } + + for(type = 0; type < 3; type++) { + /* This switch decides the order in which the states are applied */ + switch(type) { + case 0: cur = misc; break; + case 1: cur = fragment->states; break; + case 2: cur = vertex; break; + default: cur = NULL; /* Stupid compiler */ + } + if(!cur) continue; + + /* GL extension filtering should not prevent multiple handlers being applied from different + * pipeline parts + */ + memset(set, 0, sizeof(set)); + + for(i = 0; cur[i].state; i++) { + + /* Only use the first matching state with the available extension from one template. + * e.g. + * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY}, + * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 } + * + * if GL_XYZ_fancy is supported, ignore the 2nd line + */ + if(set[cur[i].state]) continue; + /* Skip state lines depending on unsupported extensions */ + if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue; + set[cur[i].state] = TRUE; + /* In some cases having an extension means that nothing has to be + * done for a state, e.g. if GL_ARB_texture_non_power_of_two is + * supported, the texture coordinate fixup can be ignored. If the + * apply function is used, mark the state set(done above) to prevent + * applying later lines, but do not record anything in the state + * table + */ + if(!cur[i].content.apply) continue; + + handlers = num_handlers(multistate_funcs[cur[i].state]); + multistate_funcs[cur[i].state][handlers] = cur[i].content.apply; + switch(handlers) { + case 0: + StateTable[cur[i].state].apply = cur[i].content.apply; + break; + case 1: + StateTable[cur[i].state].apply = multistate_apply_2; + dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(), + 0, + sizeof(**dev_multistate_funcs) * 2); + dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0]; + dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1]; + break; + case 2: + StateTable[cur[i].state].apply = multistate_apply_3; + HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]); + dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(), + 0, + sizeof(**dev_multistate_funcs) * 3); + dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0]; + dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1]; + dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2]; + break; + default: + ERR("Unexpected amount of state handlers for state %u: %u\n", + cur[i].state, handlers + 1); + } + + if(StateTable[cur[i].state].representative && + StateTable[cur[i].state].representative != cur[i].content.representative) { + FIXME("State %u has different representatives in different pipeline parts\n", + cur[i].state); + } + StateTable[cur[i].state].representative = cur[i].content.representative; + } + } +} +#undef GLINFO_LOCATION diff --git a/reactos/dll/directx/wine/wined3d/stateblock.c b/reactos/dll/directx/wine/wined3d/stateblock.c index e0a40aff094..78268d8616b 100644 --- a/reactos/dll/directx/wine/wined3d/stateblock.c +++ b/reactos/dll/directx/wine/wined3d/stateblock.c @@ -4,6 +4,7 @@ * Copyright 2002 Raphael Junqueira * Copyright 2004 Jason Edmeades * Copyright 2005 Oliver Stieber + * Copyright 2007 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -169,8 +170,7 @@ void stateblock_copy( Dest->viewport = This->viewport; Dest->material = This->material; Dest->pixelShader = This->pixelShader; - Dest->glsl_program = This->glsl_program; - memcpy(&Dest->scissorRect, &This->scissorRect, sizeof(Dest->scissorRect)); + Dest->scissorRect = This->scissorRect; /* Lights */ memset(This->activeLights, 0, sizeof(This->activeLights)); @@ -185,7 +185,7 @@ void stateblock_copy( LIST_FOR_EACH(e1, &This->lightMap[l]) { PLIGHTINFOEL *light = LIST_ENTRY(e1, PLIGHTINFOEL, entry), *light2; light2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*light)); - memcpy(light2, light, sizeof(*light)); + *light2 = *light; list_add_tail(&Dest->lightMap[l], &light2->entry); if(light2->glIndex != -1) Dest->activeLights[light2->glIndex] = light2; } @@ -342,7 +342,7 @@ static inline void record_lights(IWineD3DStateBlockImpl *This, IWineD3DStateBloc realLight = LIST_ENTRY(f, PLIGHTINFOEL, entry); if(realLight->OriginalIndex == src->OriginalIndex) { if(src->changed) { - memcpy(&src->OriginalParms, &realLight->OriginalParms, sizeof(src->OriginalParms)); + src->OriginalParms = realLight->OriginalParms; } if(src->enabledChanged) { /* Need to double check because enabledChanged does not catch enabled -> disabled -> enabled @@ -367,7 +367,7 @@ static inline void record_lights(IWineD3DStateBlockImpl *This, IWineD3DStateBloc continue; } else if(src->changed) { /* Otherwise assign defaul params */ - memcpy(&src->OriginalParms, &WINED3D_default_light, sizeof(src->OriginalParms)); + src->OriginalParms = WINED3D_default_light; } else { /* Not enabled by default */ src->glIndex = -1; @@ -477,9 +477,8 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) /* Others + Render & Texture */ for (i = 0; i < This->num_contained_transform_states; i++) { TRACE("Updating transform %d\n", i); - memcpy(&This->transforms[This->contained_transform_states[i]], - &targetStateBlock->transforms[This->contained_transform_states[i]], - sizeof(WINED3DMATRIX)); + This->transforms[This->contained_transform_states[i]] = + targetStateBlock->transforms[This->contained_transform_states[i]]; } if (This->changed.indices && ((This->pIndexData != targetStateBlock->pIndexData) @@ -506,14 +505,14 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) &This->material, sizeof(WINED3DMATERIAL)) != 0) { TRACE("Updating material\n"); - memcpy(&This->material, &targetStateBlock->material, sizeof(WINED3DMATERIAL)); + This->material = targetStateBlock->material; } if (This->changed.viewport && memcmp(&targetStateBlock->viewport, &This->viewport, sizeof(WINED3DVIEWPORT)) != 0) { TRACE("Updating viewport\n"); - memcpy(&This->viewport, &targetStateBlock->viewport, sizeof(WINED3DVIEWPORT)); + This->viewport = targetStateBlock->viewport; } if(This->changed.scissorRect && memcmp(&targetStateBlock->scissorRect, @@ -521,7 +520,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) sizeof(targetStateBlock->scissorRect))) { TRACE("Updating scissor rect\n"); - memcpy(&targetStateBlock->scissorRect, &This->scissorRect, sizeof(targetStateBlock->scissorRect)); + targetStateBlock->scissorRect = This->scissorRect; } for (i = 0; i < MAX_STREAMS; i++) { @@ -1038,6 +1037,12 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat DWORD d; } tmpfloat; unsigned int i; + IWineD3DSwapChain *swapchain; + IWineD3DSurface *backbuffer; + WINED3DSURFACE_DESC desc = {0}; + UINT width, height; + RECT scissorrect; + HRESULT hr; /* 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 @@ -1047,10 +1052,10 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat This->blockType = WINED3DSBT_INIT; /* Set some of the defaults for lights, transforms etc */ - memcpy(&This->transforms[WINED3DTS_PROJECTION], &identity, sizeof(identity)); - memcpy(&This->transforms[WINED3DTS_VIEW], &identity, sizeof(identity)); + memcpy(&This->transforms[WINED3DTS_PROJECTION], identity, sizeof(identity)); + memcpy(&This->transforms[WINED3DTS_VIEW], identity, sizeof(identity)); for (i = 0; i < 256; ++i) { - memcpy(&This->transforms[WINED3DTS_WORLDMATRIX(i)], &identity, sizeof(identity)); + memcpy(&This->transforms[WINED3DTS_WORLDMATRIX(i)], identity, sizeof(identity)); } TRACE("Render states\n"); @@ -1194,7 +1199,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat /* Texture Stage States - Put directly into state block, we will call function below */ for (i = 0; i < MAX_TEXTURES; i++) { TRACE("Setting up default texture states for texture Stage %d\n", i); - memcpy(&This->transforms[WINED3DTS_TEXTURE0 + i], &identity, sizeof(identity)); + memcpy(&This->transforms[WINED3DTS_TEXTURE0 + i], identity, sizeof(identity)); This->textureState[i][WINED3DTSS_COLOROP ] = (i==0)? WINED3DTOP_MODULATE : WINED3DTOP_DISABLE; This->textureState[i][WINED3DTSS_COLORARG1 ] = WINED3DTA_TEXTURE; This->textureState[i][WINED3DTSS_COLORARG2 ] = WINED3DTA_CURRENT; @@ -1234,71 +1239,35 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat This->samplerState[i][WINED3DSAMP_DMAPOFFSET ] = 0; /* TODO: Vertex offset in the presampled displacement map */ } - /* Under DirectX you can have texture stage operations even if no texture is - bound, whereas opengl will only do texture operations when a valid texture is - bound. We emulate this by creating dummy textures and binding them to each - texture stage, but disable all stages by default. Hence if a stage is enabled - then the default texture will kick in until replaced by a SetTexture call */ - ENTER_GL(); - - if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { - /* The dummy texture does not have client storage backing */ - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); - checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)"); - } - for (i = 0; i < GL_LIMITS(textures); i++) { - GLubyte white = 255; - - /* Note this avoids calling settexture, so pretend it has been called */ + for(i = 0; i < GL_LIMITS(textures); i++) { + /* Note: This avoids calling SetTexture, so pretend it has been called */ This->changed.textures[i] = TRUE; This->textures[i] = NULL; + } - /* Make appropriate texture active */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); - checkGLcall("glActiveTextureARB"); - } else if (i > 0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + /* Set the default scissor rect values */ + desc.Width = &width; + desc.Height = &height; + + /* check the return values, because the GetBackBuffer call isn't valid for ddraw */ + hr = IWineD3DDevice_GetSwapChain(device, 0, &swapchain); + if( hr == WINED3D_OK && swapchain != NULL) { + hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer); + if( hr == WINED3D_OK && backbuffer != NULL) { + IWineD3DSurface_GetDesc(backbuffer, &desc); + IWineD3DSurface_Release(backbuffer); + + scissorrect.left = 0; + scissorrect.right = width; + scissorrect.top = 0; + scissorrect.bottom = height; + hr = IWineD3DDevice_SetScissorRect(device, &scissorrect); + if( hr != WINED3D_OK ) { + ERR("This should never happen, expect rendering issues!\n"); + } } - - /* Generate an opengl texture name */ - glGenTextures(1, &ThisDevice->dummyTextureName[i]); - checkGLcall("glGenTextures"); - TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]); - - /* Generate a dummy 2d texture (not using 1d because they cause many - * DRI drivers fall back to sw) */ - This->textureDimensions[i] = GL_TEXTURE_2D; - glBindTexture(GL_TEXTURE_2D, ThisDevice->dummyTextureName[i]); - checkGLcall("glBindTexture"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white); - checkGLcall("glTexImage2D"); + IWineD3DSwapChain_Release(swapchain); } - if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { - /* Reenable because if supported it is enabled by default */ - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); - checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)"); - } - - LEAVE_GL(); - - - /* Defaulting palettes - Note these are device wide but reinitialized here for convenience*/ - for (i = 0; i < MAX_PALETTES; ++i) { - int j; - for (j = 0; j < 256; ++j) { - This->wineD3DDevice->palettes[i][j].peRed = 0xFF; - This->wineD3DDevice->palettes[i][j].peGreen = 0xFF; - This->wineD3DDevice->palettes[i][j].peBlue = 0xFF; - This->wineD3DDevice->palettes[i][j].peFlags = 0xFF; - } - } - This->wineD3DDevice->currentPalette = 0; - - /* Set default GLSL program to NULL. We won't actually create one - * until the app sets a vertex or pixel shader */ - This->glsl_program = NULL; TRACE("-----------------------> Device defaults now set up...\n"); return WINED3D_OK; diff --git a/reactos/dll/directx/wine/wined3d/surface.c b/reactos/dll/directx/wine/wined3d/surface.c index df617dd1f45..be6ffb33c85 100644 --- a/reactos/dll/directx/wine/wined3d/surface.c +++ b/reactos/dll/directx/wine/wined3d/surface.c @@ -7,9 +7,9 @@ * Copyright 2002-2003 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber - * Copyright 2006-2007 Stefan Dösinger for CodeWeavers - * Copyright 2007 Henri Verbeet - * Copyright 2006-2007 Roderick Colenbrander + * Copyright 2006-2008 Stefan Dösinger for CodeWeavers + * Copyright 2007-2008 Henri Verbeet + * Copyright 2006-2008 Roderick Colenbrander * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,33 +35,71 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf); static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey); +static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert); +static inline void clear_unused_channels(IWineD3DSurfaceImpl *This); +static void surface_remove_pbo(IWineD3DSurfaceImpl *This); +static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) { + int active_sampler; + + /* We don't need a specific texture unit, but after binding the texture the current unit is dirty. + * Read the unit back instead of switching to 0, this avoids messing around with the state manager's + * gl states. The current texture unit should always be a valid one. + * + * To be more specific, this is tricky because we can implicitly be called + * from sampler() in state.c. This means we can't touch anything other than + * whatever happens to be the currently active texture, or we would risk + * marking already applied sampler states dirty again. + * + * TODO: Track the current active texture per GL context instead of using glGet + */ + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + GLint active_texture; + ENTER_GL(); + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); + LEAVE_GL(); + active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB]; + } else { + active_sampler = 0; + } + + if (active_sampler != -1) { + IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler)); + } + IWineD3DSurface_BindTexture((IWineD3DSurface *)This); +} + +/* 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((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) && (render_target->resource.format == WINED3DFMT_P8)) + return TRUE; + } + return FALSE; +} + +/* This call just downloads data, the caller is responsible for activating the + * right context and binding the correct texture. */ static void surface_download_data(IWineD3DSurfaceImpl *This) { - IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; - if (0 == This->glDescription.textureName) { ERR("Surface does not have a texture, but SFLAG_INTEXTURE is set\n"); return; } - if(myDevice->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) { - ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + /* Only support read back of converted P8 surfaces */ + if(This->Flags & SFLAG_CONVERTED && (This->resource.format != WINED3DFMT_P8)) { + FIXME("Read back converted textures unsupported, format=%s\n", debug_d3dformat(This->resource.format)); + return; } ENTER_GL(); - /* Make sure that a proper texture unit is selected, bind the texture - * and dirtify the sampler to restore the texture on the next draw - */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); - checkGLcall("glActiveTextureARB"); - } - IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0)); - IWineD3DSurface_BindTexture((IWineD3DSurface *) This); if (This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 || - This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) { + This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 || + This->resource.format == WINED3DFMT_ATI2N) { if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */ FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This); } else { @@ -83,14 +121,16 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { LEAVE_GL(); } else { void *mem; + GLenum format = This->glDescription.glFormat; + GLenum type = This->glDescription.glType; int src_pitch = 0; int dst_pitch = 0; - if(This->Flags & SFLAG_CONVERTED) { - FIXME("Read back converted textures unsupported\n"); - LEAVE_GL(); - return; - } + /* In case of P8 the index is stored in the alpha component if the primary render target uses P8 */ + if(This->resource.format == WINED3DFMT_P8 && primary_render_target_is_p8(This->resource.wineD3DDevice)) { + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + } if (This->Flags & SFLAG_NONPOW2) { unsigned char alignment = This->resource.wineD3DDevice->surface_alignment; @@ -103,21 +143,21 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { } TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level, - This->glDescription.glFormat, This->glDescription.glType, mem); + format, type, mem); if(This->Flags & SFLAG_PBO) { GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); - glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, - This->glDescription.glType, NULL); + glGetTexImage(This->glDescription.target, This->glDescription.level, format, + type, NULL); checkGLcall("glGetTexImage()"); GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); checkGLcall("glBindBufferARB"); } else { - glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, - This->glDescription.glType, mem); + glGetTexImage(This->glDescription.target, This->glDescription.level, format, + type, mem); checkGLcall("glGetTexImage()"); } LEAVE_GL(); @@ -193,10 +233,16 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { This->Flags |= SFLAG_INSYSMEM; } +/* This call just uploads data, the caller is responsible for activating the + * right context and binding the correct texture. */ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) { + + if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->heightscale; + if (This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 || - This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) { + This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 || + This->resource.format == WINED3DFMT_ATI2N) { if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { FIXME("Using DXT1/3/5 without advertized support\n"); } else { @@ -249,16 +295,21 @@ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsi } } +/* This call just allocates the texture, the caller is responsible for + * activating the right context and binding the correct texture. */ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) { BOOL enable_client_storage = FALSE; BYTE *mem = NULL; + if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->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->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type); if (This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 || - This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) { + This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 || + This->resource.format == WINED3DFMT_ATI2N) { /* glCompressedTexImage2D does not accept NULL pointers, so we cannot allocate a compressed texture without uploading data */ TRACE("Not allocating compressed surfaces, surface_upload_data will specify them\n"); @@ -269,8 +320,10 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, /* Neither NONPOW2, DIBSECTION nor OVERSIZE flags can be set on compressed textures */ This->Flags |= SFLAG_CLIENT; mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); + ENTER_GL(); GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal, width, height, 0 /* border */, This->resource.size, mem)); + LEAVE_GL(); } return; @@ -348,7 +401,7 @@ void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int wi GL_EXTCALL(glGenRenderbuffersEXT(1, &renderbuffer)); GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer)); - GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, glDesc->glFormat, width, height)); + GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, glDesc->glInternal, width, height)); entry = HeapAlloc(GetProcessHeap(), 0, sizeof(renderbuffer_entry_t)); entry->width = width; @@ -385,24 +438,22 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); if (ref == 0) { - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; renderbuffer_entry_t *entry, *entry2; TRACE("(%p) : cleaning up\n", This); + /* Need a context to destroy the texture. Use the currently active render target, but only if + * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above. + * When destroying the primary rt, Uninit3D will activate a context before doing anything + */ + if(device->render_targets && device->render_targets[0]) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } + + ENTER_GL(); if (This->glDescription.textureName != 0) { /* release the openGL texture.. */ - - /* Need a context to destroy the texture. Use the currently active render target, but only if - * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above. - * When destroying the primary rt, Uninit3D will activate a context before doing anything - */ - if(device->render_targets && device->render_targets[0]) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - TRACE("Deleting texture %d\n", This->glDescription.textureName); - ENTER_GL(); glDeleteTextures(1, &This->glDescription.textureName); - LEAVE_GL(); } if(This->Flags & SFLAG_PBO) { @@ -410,6 +461,12 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo)); } + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) { + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); + HeapFree(GetProcessHeap(), 0, entry); + } + LEAVE_GL(); + if(This->Flags & SFLAG_DIBSECTION) { /* Release the DC */ SelectObject(This->hDC, This->dib.holdbitmap); @@ -424,12 +481,9 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { HeapFree(GetProcessHeap(), 0, This->palette9); IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface); - if(iface == device->ddraw_primary) - device->ddraw_primary = NULL; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) { - GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); - HeapFree(GetProcessHeap(), 0, entry); + if(This->overlay_dest) { + list_remove(&This->overlay_entry); } TRACE("(%p) Released\n", This); @@ -455,35 +509,116 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture_PreLoad(baseTexture); IWineD3DBaseTexture_Release(baseTexture); } else { - TRACE("(%p) : About to load surface\n", This); + TRACE("(%p) : About to load surface\n", This); - if(!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if(!device->isInDraw) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } + + if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { + if(palette9_changed(This)) { + 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); + /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */ + IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); + } + } + + IWineD3DSurface_LoadTexture(iface, FALSE); + + if (This->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->glDescription.textureName, &tmp); + LEAVE_GL(); + } } + return; +} + +static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { + 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)); ENTER_GL(); - glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */ - if (!This->glDescription.level) { - if (!This->glDescription.textureName) { - glGenTextures(1, &This->glDescription.textureName); - checkGLcall("glGenTextures"); - TRACE("Surface %p given name %d\n", This, This->glDescription.textureName); - } - glBindTexture(This->glDescription.target, This->glDescription.textureName); - checkGLcall("glBindTexture"); - IWineD3DSurface_LoadTexture(iface, FALSE); - /* This is where we should be reducing the amount of GLMemoryUsed */ - } else if (This->glDescription.textureName) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */ - /* assume this is a coding error not a real error for now */ - FIXME("Mipmap surface has a glTexture bound to it!\n"); - } - if (This->resource.pool == WINED3DPOOL_DEFAULT) { - /* Tell opengl to try and keep this texture in video ram (well mostly) */ - GLclampf tmp; - tmp = 0.9f; - glPrioritizeTextures(1, &This->glDescription.textureName, &tmp); - } + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); + checkGLcall("glBindBuffer(GL_PIXEL_UNPACK_BUFFER, This->pbo)"); + GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory)); + checkGLcall("glGetBufferSubData"); + GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo)); + checkGLcall("glDeleteBuffers"); LEAVE_GL(); + + This->pbo = 0; + This->Flags &= ~SFLAG_PBO; +} + +static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { + IWineD3DBaseTexture *texture = NULL; + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + renderbuffer_entry_t *entry, *entry2; + TRACE("(%p)\n", iface); + + if(This->resource.pool == WINED3DPOOL_DEFAULT) { + /* Default pool resources are supposed to be destroyed before Reset is called. + * Implicit resources stay however. So this means we have an implicit render target + * or depth stencil. The content may be destroyed, but we still have to tear down + * opengl resources, so we cannot leave early. + * + * Put the most up to date surface location into the drawable. D3D-wise this content + * is undefined, so it would be nowhere, but that would make the location management + * more complicated. The drawable is a sane location, because if we mark sysmem or + * texture up to date, drawPrim will copy the uninitialized texture or sysmem to the + * uninitialized drawable. That's pointless and we'd have to allocate the texture / + * sysmem copy here. + */ + if (This->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) { + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + } else { + IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, TRUE); + } + } else { + /* Load the surface into system memory */ + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); + } + IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); + This->Flags &= ~SFLAG_ALLOCATED; + + /* Destroy PBOs, but load them into real sysmem before */ + if(This->Flags & SFLAG_PBO) { + surface_remove_pbo(This); + } + + /* Destroy fbo render buffers. This is needed for implicit render targets, for + * all application-created targets the application has to release the surface + * before calling _Reset + */ + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) { + ENTER_GL(); + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); + LEAVE_GL(); + list_remove(&entry->entry); + HeapFree(GetProcessHeap(), 0, entry); + } + list_init(&This->renderbuffers); + This->current_renderbuffer = NULL; + + /* If we're in a texture, the texture name belongs to the texture. Otherwise, + * destroy it + */ + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **) &texture); + if(!texture) { + ENTER_GL(); + glDeleteTextures(1, &This->glDescription.textureName); + This->glDescription.textureName = 0; + LEAVE_GL(); + } else { + IWineD3DBaseTexture_Release(texture); } return; } @@ -494,10 +629,24 @@ void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target); + TRACE("(%p) : setting textureName %u, target %#x\n", This, textureName, target); if (This->glDescription.textureName == 0 && textureName != 0) { IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); - IWineD3DSurface_AddDirtyRect(iface, NULL); + if((This->Flags & SFLAG_LOCATIONS) == 0) { + /* In 1.0-rc4 and earlier, AddDirtyRect was called in the place of this if condition. + * This had the problem that a correctly set INDRAWABLE flag was removed if the PreLoad + * during the offscreen rendering readback triggered the creation of the GL texture. + * The change intended to keep the INDRAWABLE intact. To prevent unintended side effects + * before release, set the INSYSMEM flag like the old AddDirtyRect did. + */ + WARN("Wine 1.0 safety path hit\n"); + This->Flags |= SFLAG_INSYSMEM; + } + } + if(target == GL_TEXTURE_RECTANGLE_ARB && This->glDescription.target != target) { + This->Flags &= ~SFLAG_NORMCOORD; + } else if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB && target != GL_TEXTURE_RECTANGLE_ARB) { + This->Flags |= SFLAG_NORMCOORD; } This->glDescription.textureName = textureName; This->glDescription.target = target; @@ -520,6 +669,7 @@ const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) { return (CONST void*)(This->resource.allocatedMemory); } +/* Read the framebuffer back into the surface */ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) { IWineD3DSwapChainImpl *swapchain; IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; @@ -586,7 +736,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v { case WINED3DFMT_P8: { - if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { + if(primary_render_target_is_p8(myDevice)) { /* In case of P8 render targets the index is stored in the alpha component */ fmt = GL_ALPHA; type = GL_UNSIGNED_BYTE; @@ -668,7 +818,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v } top = mem + pitch * local_rect.top; - bottom = ((BYTE *) mem) + pitch * ( local_rect.bottom - local_rect.top - 1); + bottom = mem + pitch * ( local_rect.bottom - local_rect.top - 1); for(i = 0; i < (local_rect.bottom - local_rect.top) / 2; i++) { memcpy(row, top + off, len); memcpy(top + off, bottom + off, len); @@ -685,25 +835,30 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v } } + LEAVE_GL(); + /* For P8 textures we need to perform an inverse palette lookup. This is done by searching for a palette * index which matches the RGB value. Note this isn't guaranteed to work when there are multiple entries for * the same color but we have no choice. - * In case of render targets, the index is stored in the alpha component so no conversion is needed. + * In case of P8 render targets, the index is stored in the alpha component so no conversion is needed. */ - if((This->resource.format == WINED3DFMT_P8) && !(This->resource.usage & WINED3DUSAGE_RENDERTARGET)) { - PALETTEENTRY *pal; + if((This->resource.format == WINED3DFMT_P8) && !primary_render_target_is_p8(myDevice)) { + PALETTEENTRY *pal = NULL; DWORD width = pitch / 3; int x, y, c; + if(This->palette) { pal = This->palette->palents; } else { - pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette]; + ERR("Palette is missing, cannot perform inverse palette lookup\n"); + HeapFree(GetProcessHeap(), 0, mem); + return ; } for(y = local_rect.top; y < local_rect.bottom; y++) { for(x = local_rect.left; x < local_rect.right; x++) { /* start lines pixels */ - BYTE *blue = (BYTE *) ((BYTE *) mem) + y * pitch + x * (sizeof(BYTE) * 3); + BYTE *blue = mem + y * pitch + x * (sizeof(BYTE) * 3); BYTE *green = blue + 1; BYTE *red = green + 1; @@ -720,7 +875,75 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v } HeapFree(GetProcessHeap(), 0, mem); } +} + +/* Read the framebuffer contents into a texture */ +static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This) +{ + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + IWineD3DSwapChainImpl *swapchain; + int bpp; + GLenum format, internal, type; + CONVERT_TYPES convert; + GLint prevRead; + + d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb); + + IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain); + /* 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. + */ + ActivateContext(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD); + surface_bind_and_dirtify(This); + ENTER_GL(); + + glGetIntegerv(GL_READ_BUFFER, &prevRead); + + /* 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(!swapchain) { + /* 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(device->offscreenBuffer); + } else { + GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain); + TRACE("Locking %#x buffer\n", buffer); + glReadBuffer(buffer); + checkGLcall("glReadBuffer"); + + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + } + + if(!(This->Flags & SFLAG_ALLOCATED)) { + surface_allocate_surface(This, internal, This->pow2Width, + This->pow2Height, format, type); + } + + clear_unused_channels(This); + + /* If !SrcIsUpsideDown we should flip the surface. + * This can be done using glCopyTexSubImage2D but this + * is VERY slow, so don't do that. We should prevent + * this code from getting called in such cases or perhaps + * we can use FBOs */ + + glCopyTexSubImage2D(This->glDescription.target, + This->glDescription.level, + 0, 0, 0, 0, + This->currentDesc.Width, + This->currentDesc.Height); + checkGLcall("glCopyTexSubImage2D"); + + glReadBuffer(prevRead); + vcheckGLcall("glReadBuffer"); + LEAVE_GL(); + TRACE("Updated target %d\n", This->glDescription.target); } static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { @@ -742,6 +965,9 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { */ if(GL_SUPPORT(ARB_PIXEL_BUFFER_OBJECT) && (This->Flags & SFLAG_DYNLOCK) && !(This->Flags & (SFLAG_PBO | SFLAG_CONVERTED | SFLAG_NONPOW2)) && (This->resource.pool != WINED3DPOOL_SYSTEMMEM)) { GLenum error; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glGenBuffersARB(1, &This->pbo)); @@ -809,7 +1035,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED if (Flags & WINED3DLOCK_DISCARD) { /* Set SFLAG_INSYSMEM, so we'll never try to download the data from the texture. */ TRACE("WINED3DLOCK_DISCARD flag passed, marking local copy as up to date\n"); + surface_prepare_system_memory(This); /* Makes sure memory is allocated */ This->Flags |= SFLAG_INSYSMEM; + goto lock_end; } if (This->Flags & SFLAG_INSYSMEM) { @@ -820,7 +1048,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED /* Now download the surface content from opengl * Use the render target readback if the surface is on a swapchain(=onscreen render target) or the current primary target - * Offscreen targets which are not active at the moment or are higher targets(fbos) can be locked with the texture path + * Offscreen targets which are not active at the moment or are higher targets(FBOs) can be locked with the texture path */ IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain); if(swapchain || iface == myDevice->render_targets[0]) { @@ -933,16 +1161,12 @@ lock_end: return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags); } -static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) { +static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem) { GLint prev_store; GLint prev_rasterpos[4]; GLint skipBytes = 0; - BOOL storechanged = FALSE, memory_allocated = FALSE; - GLint fmt, type; - BYTE *mem; - UINT bpp; UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */ - IWineD3DDeviceImpl *myDevice = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice; + IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; IWineD3DSwapChainImpl *swapchain; /* Activate the correct context for the render target */ @@ -964,11 +1188,6 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) { IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain); } - glDisable(GL_TEXTURE_2D); - vcheckGLcall("glDisable(GL_TEXTURE_2D)"); - - glFlush(); - vcheckGLcall("glFlush"); glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store); vcheckGLcall("glIntegerv"); glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]); @@ -989,7 +1208,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) { * catch to put the dib section in InSync mode, which leads to a crash * and a blocked x server on my radeon card. * - * The following lines read the dib section so it is put in inSync mode + * The following lines read the dib section so it is put in InSync mode * before glDrawPixels is called and the crash is prevented. There won't * be any interfering gdi accesses, because UnlockRect is called from * ReleaseDC, and the app won't use the dc any more afterwards. @@ -999,141 +1218,25 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) { read = This->resource.allocatedMemory[0]; } - switch (This->resource.format) { - /* No special care needed */ - case WINED3DFMT_A4R4G4B4: - case WINED3DFMT_R5G6B5: - case WINED3DFMT_A1R5G5B5: - case WINED3DFMT_R8G8B8: - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - break; - - case WINED3DFMT_X4R4G4B4: - { - int size; - unsigned short *data; - data = (unsigned short *)This->resource.allocatedMemory; - size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left); - while(size > 0) { - *data |= 0xF000; - data++; - size--; - } - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - } - break; - - case WINED3DFMT_X1R5G5B5: - { - int size; - unsigned short *data; - data = (unsigned short *)This->resource.allocatedMemory; - size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left); - while(size > 0) { - *data |= 0x8000; - data++; - size--; - } - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - } - break; - - case WINED3DFMT_X8R8G8B8: - { - /* make sure the X byte is set to alpha on, since it - could be any random value. This fixes the intro movie in Pirates! */ - int size; - unsigned int *data; - data = (unsigned int *)This->resource.allocatedMemory; - size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left); - while(size > 0) { - *data |= 0xFF000000; - data++; - size--; - } - } - /* Fall through */ - - case WINED3DFMT_A8R8G8B8: - { - glPixelStorei(GL_PACK_SWAP_BYTES, TRUE); - vcheckGLcall("glPixelStorei"); - storechanged = TRUE; - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - } - break; - - case WINED3DFMT_A2R10G10B10: - { - glPixelStorei(GL_PACK_SWAP_BYTES, TRUE); - vcheckGLcall("glPixelStorei"); - storechanged = TRUE; - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - } - break; - - case WINED3DFMT_P8: - { - int height = This->glRect.bottom - This->glRect.top; - type = GL_UNSIGNED_BYTE; - fmt = GL_RGBA; - - mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD)); - if(!mem) { - ERR("Out of memory\n"); - goto cleanup; - } - memory_allocated = TRUE; - d3dfmt_convert_surface(This->resource.allocatedMemory, - mem, - pitch, - pitch, - height, - pitch * 4, - CONVERT_PALETTED, - This); - bpp = This->bytesPerPixel * 4; - pitch *= 4; - } - break; - - default: - FIXME("Unsupported Format %u in locking func\n", This->resource.format); - - /* Give it a try */ - type = This->glDescription.glType; - fmt = This->glDescription.glFormat; - mem = This->resource.allocatedMemory; - bpp = This->bytesPerPixel; - } - if(This->Flags & SFLAG_PBO) { GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); } - glDrawPixels(This->lockedRect.right - This->lockedRect.left, - (This->lockedRect.bottom - This->lockedRect.top)-1, - fmt, type, - mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top); - checkGLcall("glDrawPixels"); + /* When the surface is locked we only have to refresh the locked part else we need to update the whole image */ + if(This->Flags & SFLAG_LOCKED) { + glDrawPixels(This->lockedRect.right - This->lockedRect.left, + (This->lockedRect.bottom - This->lockedRect.top)-1, + fmt, type, + mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top); + checkGLcall("glDrawPixels"); + } else { + glDrawPixels(This->currentDesc.Width, + This->currentDesc.Height, + fmt, type, mem); + checkGLcall("glDrawPixels"); + } -cleanup: if(This->Flags & SFLAG_PBO) { GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); checkGLcall("glBindBufferARB"); @@ -1148,18 +1251,6 @@ cleanup: /* Reset to previous pack row length */ glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes); vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH"); - if(storechanged) { - glPixelStorei(GL_PACK_SWAP_BYTES, prev_store); - vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES"); - } - - /* Blitting environment requires that 2D texturing is enabled. It was turned off before, - * turn it on again - */ - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable(GL_TEXTURE_2D)"); - - if(memory_allocated) HeapFree(GetProcessHeap(), 0, mem); if(!swapchain) { glDrawBuffer(myDevice->offscreenBuffer); @@ -1208,13 +1299,14 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain); if(swapchain || (myDevice->render_targets && iface == myDevice->render_targets[0])) { + if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) { static BOOL warned = FALSE; if(!warned) { ERR("The application tries to write to the render target, but render target locking is disabled\n"); warned = TRUE; } - if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); goto unlock_end; } @@ -1233,14 +1325,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { case RTL_READTEX: case RTL_TEXTEX: ActivateContext(myDevice, iface, CTXUSAGE_BLIT); - ENTER_GL(); - if (This->glDescription.textureName == 0) { - glGenTextures(1, &This->glDescription.textureName); - checkGLcall("glGenTextures"); - } - glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName); - checkGLcall("glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);"); - LEAVE_GL(); IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */); /* drop through */ @@ -1286,6 +1370,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { unlock_end: This->Flags &= ~SFLAG_LOCKED; memset(&This->lockedRect, 0, sizeof(RECT)); + + /* Overlays have to be redrawn manually after changes with the GL implementation */ + if(This->overlay_dest) { + IWineD3DSurface_DrawOverlay(iface); + } return WINED3D_OK; } @@ -1310,6 +1399,14 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) { if (This->Flags & SFLAG_LOCKED) return WINED3DERR_INVALIDCALL; + /* According to Direct3D9 docs, only these formats are supported */ + if (((IWineD3DImpl *)This->resource.wineD3DDevice->wineD3D)->dxVersion > 7) { + if (This->resource.format != WINED3DFMT_R5G6B5 && + This->resource.format != WINED3DFMT_X1R5G5B5 && + This->resource.format != WINED3DFMT_R8G8B8 && + This->resource.format != WINED3DFMT_X8R8G8B8) return WINED3DERR_INVALIDCALL; + } + memset(&lock, 0, sizeof(lock)); /* To be sure */ /* Create a DIB section if there isn't a hdc yet */ @@ -1343,29 +1440,31 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) { if(This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { + /* GetDC on palettized formats is unsupported in D3D9, and the method is missing in + D3D8, so this should only be used for DX <=7 surfaces (with non-device palettes) */ unsigned int n; + PALETTEENTRY *pal = NULL; + if(This->palette) { - PALETTEENTRY ent[256]; - - GetPaletteEntries(This->palette->hpal, 0, 256, ent); - for (n=0; n<256; n++) { - col[n].rgbRed = ent[n].peRed; - col[n].rgbGreen = ent[n].peGreen; - col[n].rgbBlue = ent[n].peBlue; - col[n].rgbReserved = 0; - } + pal = This->palette->palents; } else { - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + IWineD3DSurfaceImpl *dds_primary; + IWineD3DSwapChainImpl *swapchain; + swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0]; + dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer; + if (dds_primary && dds_primary->palette) + pal = dds_primary->palette->palents; + } + if (pal) { for (n=0; n<256; n++) { - col[n].rgbRed = device->palettes[device->currentPalette][n].peRed; - col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen; - col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue; + col[n].rgbRed = pal[n].peRed; + col[n].rgbGreen = pal[n].peGreen; + col[n].rgbBlue = pal[n].peBlue; col[n].rgbReserved = 0; } - + SetDIBColorTable(This->hDC, 0, 256, col); } - SetDIBColorTable(This->hDC, 0, 256, col); } *pHDC = This->hDC; @@ -1409,16 +1508,22 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT); const GlPixelFormatDesc *glDesc; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL p8_render_target = FALSE; getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc); /* Default values: From the surface */ *format = glDesc->glFormat; - *internal = srgb_mode?glDesc->glGammaInternal:glDesc->glInternal; *type = glDesc->glType; *convert = NO_CONVERSION; *target_bpp = This->bytesPerPixel; + if(srgb_mode) { + *internal = glDesc->glGammaInternal; + } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { + *internal = glDesc->rtInternal; + } else { + *internal = glDesc->glInternal; + } + /* Ok, now look if we have to do any conversion */ switch(This->resource.format) { case WINED3DFMT_P8: @@ -1426,17 +1531,18 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ Paletted Texture **************** */ - if (device->render_targets && device->render_targets[0]) { - IWineD3DSurfaceImpl* render_target = (IWineD3DSurfaceImpl*)device->render_targets[0]; - if((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) && (render_target->resource.format == WINED3DFMT_P8)) - p8_render_target = TRUE; - } - - /* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used - * for texturing as it won't work for calls like glDraw-/glReadPixels and 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. + /* 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. + * 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_SUPPORT(EXT_PALETTED_TEXTURE) || (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && p8_render_target)) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) { + if( !(GL_SUPPORT(EXT_PALETTED_TEXTURE) || + (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && + device->render_targets && + This == (IWineD3DSurfaceImpl*)device->render_targets[0])) || + colorkey_active || !use_texturing ) { *format = GL_RGBA; *internal = GL_RGBA; *type = GL_UNSIGNED_BYTE; @@ -1447,8 +1553,8 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *convert = CONVERT_PALETTED; } } - else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { - *format = GL_RED; + else if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + *format = GL_ALPHA; *internal = GL_RGBA; *type = GL_UNSIGNED_BYTE; *target_bpp = 1; @@ -1610,6 +1716,14 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *target_bpp = 6; break; + case WINED3DFMT_G16R16: + *convert = CONVERT_G16R16; + *format = GL_RGB; + *internal = GL_RGB16_EXT; + *type = GL_UNSIGNED_SHORT; + *target_bpp = 6; + break; + default: break; } @@ -1716,6 +1830,29 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN } break; + case CONVERT_RGB32_888: + { + /* Converting X8R8G8B8 format to R8G8B8A8 with color-keying. */ + unsigned int x, y; + for (y = 0; y < height; y++) + { + source = src + pitch * y; + dest = dst + outpitch * y; + for (x = 0; x < width; x++) { + DWORD color = 0xffffff & *(DWORD*)source; + DWORD dstcolor = color << 8; + if ((color < This->SrcBltCKey.dwColorSpaceLowValue) || + (color > This->SrcBltCKey.dwColorSpaceHighValue)) { + dstcolor |= 0xff; + } + *(DWORD*)dest = dstcolor; + source += 4; + dest += 4; + } + } + } + break; + case CONVERT_V8U8: { unsigned int x, y; @@ -1723,7 +1860,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN unsigned char *Dest; for(y = 0; y < height; y++) { Source = (short *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { long color = (*Source++); /* B */ Dest[0] = 0xff; @@ -1761,7 +1898,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN unsigned char *Dest; for(y = 0; y < height; y++) { Source = (DWORD *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { long color = (*Source++); /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */ @@ -1787,7 +1924,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN */ for(y = 0; y < height; y++) { Source = (WORD *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { short color = (*Source++); unsigned char l = ((color >> 10) & 0xfc); @@ -1840,7 +1977,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN */ for(y = 0; y < height; y++) { Source = (DWORD *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { long color = (*Source++); /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */ @@ -1857,7 +1994,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN */ for(y = 0; y < height; y++) { Source = (DWORD *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { long color = (*Source++); /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */ @@ -1876,8 +2013,8 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN unsigned char *Source; unsigned char *Dest; for(y = 0; y < height; y++) { - Source = (unsigned char *) (src + y * pitch); - Dest = (unsigned char *) (dst + y * outpitch); + Source = src + y * pitch; + Dest = dst + y * outpitch; for (x = 0; x < width; x++ ) { unsigned char color = (*Source++); /* A */ Dest[1] = (color & 0xf0) << 0; @@ -1926,6 +2063,28 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN } break; } + + case CONVERT_G16R16: + { + unsigned int x, y; + WORD *Source; + WORD *Dest; + + for(y = 0; y < height; y++) { + Source = (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; + Dest[2] = 0xffff; + Dest += 3; + } + } + break; + } + default: ERR("Unsupported conversation type %d\n", convert); } @@ -1936,6 +2095,7 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] IWineD3DPaletteImpl* pal = This->palette; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; BOOL index_in_alpha = FALSE; + int dxVersion = ( (IWineD3DImpl *) device->wineD3D)->dxVersion; int i; /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets. @@ -1943,32 +2103,26 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] * is slow. Further RGB->P8 conversion is not possible because palettes can have * duplicate entries. Store the color key in the unused alpha component to speed the * download up and to make conversion unneeded. */ - if (device->render_targets && device->render_targets[0]) { - IWineD3DSurfaceImpl* render_target = (IWineD3DSurfaceImpl*)device->render_targets[0]; - - if(render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) - index_in_alpha = TRUE; - } + index_in_alpha = primary_render_target_is_p8(device); if (pal == NULL) { - /* Still no palette? Use the device's palette */ - /* Get the surface's palette */ - for (i = 0; i < 256; i++) { - table[i][0] = device->palettes[device->currentPalette][i].peRed; - table[i][1] = device->palettes[device->currentPalette][i].peGreen; - table[i][2] = device->palettes[device->currentPalette][i].peBlue; - + /* In DirectDraw the palette is a property of the surface, there are no such things as device palettes. */ + if(dxVersion <= 7) { + ERR("This code should never get entered for DirectDraw!, expect problems\n"); if(index_in_alpha) { - table[i][3] = i; - } else if (colorkey && - (i >= This->SrcBltCKey.dwColorSpaceLowValue) && - (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { - /* We should maybe here put a more 'neutral' color than the standard bright purple - one often used by application to prevent the nice purple borders when bi-linear - filtering is on */ - table[i][3] = 0x00; - } else { - table[i][3] = 0xFF; + /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if + there's no palette at this time. */ + for (i = 0; i < 256; i++) table[i][3] = i; + } + } else { + /* Direct3D >= 8 palette usage style: P8 textures use device palettes, palette entry format is A8R8G8B8, + alpha is stored in peFlags and may be used by the app if D3DPTEXTURECAPS_ALPHAPALETTE device + capability flag is present (wine does advertise this capability) */ + for (i = 0; i < 256; i++) { + table[i][0] = device->palettes[device->currentPalette][i].peRed; + table[i][1] = device->palettes[device->currentPalette][i].peGreen; + table[i][2] = device->palettes[device->currentPalette][i].peBlue; + table[i][3] = device->palettes[device->currentPalette][i].peFlags; } } } else { @@ -1979,15 +2133,13 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] table[i][1] = pal->palents[i].peGreen; table[i][2] = pal->palents[i].peBlue; + /* When index_in_alpha is the palette index is stored in the alpha component. In case of a readback + we can then read GL_ALPHA. Color keying is handled in BltOverride using a GL_ALPHA_TEST using GL_NOT_EQUAL. + In case of index_in_alpha the color key itself is passed to glAlphaFunc in other cases the alpha component + of pixels that should be masked away is set to 0. */ if(index_in_alpha) { table[i][3] = i; - } - else if (colorkey && - (i >= This->SrcBltCKey.dwColorSpaceLowValue) && - (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { - /* We should maybe here put a more 'neutral' color than the standard bright purple - one often used by application to prevent the nice purple borders when bi-linear - filtering is on */ + } else if(colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue) && (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { table[i][3] = 0x00; } else if(pal->Flags & WINEDDPCAPS_ALPHA) { table[i][3] = pal->palents[i].peFlags; @@ -2002,9 +2154,9 @@ const char *fragment_palette_conversion = "!!ARBfp1.0\n" "TEMP index;\n" "PARAM constants = { 0.996, 0.00195, 0, 0 };\n" /* { 255/256, 0.5/255*255/256, 0, 0 } */ - "TEX index.x, fragment.texcoord[0], texture[0], 2D;\n" /* store the red-component of the current pixel */ - "MAD index.x, index.x, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ - "TEX result.color, index, texture[1], 1D;\n" /* use the red-component as a index in the palette to get the final color */ + "TEX index, fragment.texcoord[0], texture[0], 2D;\n" /* The alpha-component contains the palette index */ + "MAD index.a, index.a, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ + "TEX result.color, index.a, texture[1], 1D;\n" /* use the alpha-component as a index in the palette to get the final color */ "END"; /* This function is used in case of 8bit paletted textures to upload the palette. @@ -2022,7 +2174,7 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve if(GL_SUPPORT(EXT_PALETTED_TEXTURE)) { TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n"); - GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table)); + GL_EXTCALL(glColorTableEXT(This->glDescription.target,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table)); } else { @@ -2060,7 +2212,7 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve } } -static BOOL palette9_changed(IWineD3DSurfaceImpl *This) { +BOOL palette9_changed(IWineD3DSurfaceImpl *This) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; if(This->palette || (This->resource.format != WINED3DFMT_P8 && This->resource.format != WINED3DFMT_A8P8)) { @@ -2133,11 +2285,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BO /* To perform the color key conversion we need a sysmem copy of * the surface. Make sure we have it */ + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); - } else if(palette9_changed(This)) { - TRACE("Reloading surface because the d3d8/9 palette was changed\n"); + /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */ /* TODO: This is not necessarily needed with hw palettized texture support */ - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); } else { TRACE("surface is already in texture\n"); return WINED3D_OK; @@ -2203,8 +2355,26 @@ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface) { if(!device->isInDraw) { ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); } + ENTER_GL(); + + glEnable(This->glDescription.target); + + if (!This->glDescription.level) { + if (!This->glDescription.textureName) { + glGenTextures(1, &This->glDescription.textureName); + checkGLcall("glGenTextures"); + TRACE("Surface %p given name %d\n", This, This->glDescription.textureName); + } + /* This is where we should be reducing the amount of GLMemoryUsed */ + } else if (This->glDescription.textureName) { + /* Mipmap surfaces should have a base texture container */ + ERR("Mipmap surface has a glTexture bound to it!\n"); + } + glBindTexture(This->glDescription.target, This->glDescription.textureName); + checkGLcall("glBindTexture"); + LEAVE_GL(); } return; @@ -2282,6 +2452,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const ch } else { /* bind the real texture, and make sure it up to date */ IWineD3DSurface_PreLoad(iface); + surface_bind_and_dirtify(This); } allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4); ENTER_GL(); @@ -2358,7 +2529,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const ch /** * Slightly inefficient way to handle multiple dirty rects but it works :) */ -extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) { +HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DBaseTexture *baseTexture = NULL; @@ -2454,7 +2625,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) { /* Now free the old memory if any */ HeapFree(GetProcessHeap(), 0, release); } else if(This->Flags & SFLAG_USERPTR) { - /* Lockrect and GetDC will re-create the dib section and allocated memory */ + /* LockRect and GetDC will re-create the dib section and allocated memory */ This->resource.allocatedMemory = NULL; /* HeapMemory should be NULL already */ if(This->resource.heapMemory != NULL) ERR("User pointer surface has heap memory allocated\n"); @@ -2469,14 +2640,99 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) { return WINED3D_OK; } +void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) { + + /* Flip the surface contents */ + /* Flip the DC */ + { + HDC tmp; + tmp = front->hDC; + front->hDC = back->hDC; + back->hDC = tmp; + } + + /* Flip the DIBsection */ + { + HBITMAP tmp; + BOOL hasDib = front->Flags & SFLAG_DIBSECTION; + tmp = front->dib.DIBsection; + front->dib.DIBsection = back->dib.DIBsection; + back->dib.DIBsection = tmp; + + if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION; + else front->Flags &= ~SFLAG_DIBSECTION; + if(hasDib) back->Flags |= SFLAG_DIBSECTION; + else back->Flags &= ~SFLAG_DIBSECTION; + } + + /* Flip the surface data */ + { + void* tmp; + + tmp = front->dib.bitmap_data; + front->dib.bitmap_data = back->dib.bitmap_data; + back->dib.bitmap_data = tmp; + + tmp = front->resource.allocatedMemory; + front->resource.allocatedMemory = back->resource.allocatedMemory; + back->resource.allocatedMemory = tmp; + + tmp = front->resource.heapMemory; + front->resource.heapMemory = back->resource.heapMemory; + back->resource.heapMemory = tmp; + } + + /* Flip the PBO */ + { + GLuint tmp_pbo = front->pbo; + front->pbo = back->pbo; + back->pbo = tmp_pbo; + } + + /* client_memory should not be different, but just in case */ + { + BOOL tmp; + tmp = front->dib.client_memory; + front->dib.client_memory = back->dib.client_memory; + back->dib.client_memory = tmp; + } + + /* Flip the opengl texture */ + { + glDescriptor tmp_desc = back->glDescription; + back->glDescription = front->glDescription; + front->glDescription = tmp_desc; + } + + { + DWORD tmp_flags = back->Flags; + back->Flags = front->Flags; + front->Flags = tmp_flags; + } +} + static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DSwapChainImpl *swapchain = NULL; HRESULT hr; TRACE("(%p)->(%p,%x)\n", This, override, Flags); - /* Flipping is only supported on RenderTargets */ - if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return WINEDDERR_NOTFLIPPABLE; + /* Flipping is only supported on RenderTargets and overlays*/ + if( !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_OVERLAY)) ) { + WARN("Tried to flip a non-render target, non-overlay surface\n"); + return WINEDDERR_NOTFLIPPABLE; + } + + if(This->resource.usage & WINED3DUSAGE_OVERLAY) { + flip_surface(This, (IWineD3DSurfaceImpl *) override); + + /* Update the overlay if it is visible */ + if(This->overlay_dest) { + return IWineD3DSurface_DrawOverlay((IWineD3DSurface *) This); + } else { + return WINED3D_OK; + } + } if(override) { /* DDraw sets this for the X11 surfaces, so don't confuse the user @@ -2525,13 +2781,19 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); - ENTER_GL(); IWineD3DSurface_PreLoad((IWineD3DSurface *) This); + ENTER_GL(); + + /* TODO: Do we need GL_TEXTURE_2D enabled fpr copyteximage? */ + glEnable(This->glDescription.target); + checkGLcall("glEnable(This->glDescription.target)"); /* Bind the target texture */ - glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName); + glBindTexture(This->glDescription.target, This->glDescription.textureName); checkGLcall("glBindTexture"); if(!swapchain) { + TRACE("Reading from an offscreen target\n"); + upsidedown = !upsidedown; glReadBuffer(myDevice->offscreenBuffer); } else { GLenum buffer = surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain); @@ -2593,8 +2855,12 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D } } } - vcheckGLcall("glCopyTexSubImage2D"); + + /* Leave the opengl state valid for blitting */ + glDisable(This->glDescription.target); + checkGLcall("glDisable(This->glDescription.target)"); + LEAVE_GL(); } @@ -2607,49 +2873,62 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine UINT fbwidth = Src->currentDesc.Width; UINT fbheight = Src->currentDesc.Height; GLenum drawBuffer = GL_BACK; + GLenum texture_target; + BOOL noBackBufferBackup; TRACE("Using hwstretch blit\n"); /* Activate the Proper context for reading from the source surface, set it up for blitting */ ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); - ENTER_GL(); IWineD3DSurface_PreLoad((IWineD3DSurface *) This); + noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO; + if(!noBackBufferBackup && Src->glDescription.textureName == 0) { + /* Get it a description */ + IWineD3DSurface_PreLoad(SrcSurface); + } + ENTER_GL(); + /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring. * This way we don't have to wait for the 2nd readback to finish to leave this function. */ - if(GL_LIMITS(aux_buffers) >= 2) { + if(myDevice->activeContext->aux_buffers >= 2) { /* Got more than one aux buffer? Use the 2nd aux buffer */ drawBuffer = GL_AUX1; - } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && GL_LIMITS(aux_buffers) >= 1) { + } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && myDevice->activeContext->aux_buffers >= 1) { /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */ drawBuffer = GL_AUX0; } - if(!swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + if(noBackBufferBackup) { glGenTextures(1, &backup); checkGLcall("glGenTextures\n"); glBindTexture(GL_TEXTURE_2D, backup); checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)"); + texture_target = GL_TEXTURE_2D; } else { /* 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 */ - if(Src->glDescription.textureName == 0) { - /* Get it a description */ - IWineD3DSurface_PreLoad(SrcSurface); - } - glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName); - checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)"); + texture_target = Src->glDescription.target; + glBindTexture(texture_target, Src->glDescription.textureName); + checkGLcall("glBindTexture(texture_target, Src->glDescription.textureName)"); + 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; } - glReadBuffer(GL_BACK); - checkGLcall("glReadBuffer(GL_BACK)"); + if(swapchain) { + glReadBuffer(surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain)); + } else { + TRACE("Reading from an offscreen target\n"); + upsidedown = !upsidedown; + glReadBuffer(myDevice->offscreenBuffer); + } /* TODO: Only back up the part that will be overwritten */ - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, + glCopyTexSubImage2D(texture_target, 0, 0, 0 /* read offsets */, 0, 0, fbwidth, @@ -2658,10 +2937,10 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine checkGLcall("glCopyTexSubImage2D"); /* No issue with overriding these - the sampler is dirty due to blit usage */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - stateLookup[WINELOOKUP_MAGFILTER][Filter - minLookup[WINELOOKUP_MAGFILTER]]); + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, + magLookup[Filter - WINED3DTEXF_NONE]); checkGLcall("glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, minMipLookup[Filter][WINED3DTEXF_NONE]); checkGLcall("glTexParameteri"); @@ -2695,23 +2974,36 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glReadBuffer(GL_BACK); checkGLcall("glReadBuffer(GL_BACK)"); + + if(texture_target != GL_TEXTURE_2D) { + glDisable(texture_target); + glEnable(GL_TEXTURE_2D); + texture_target = GL_TEXTURE_2D; + } } checkGLcall("glEnd and previous"); - left = (float) srect->x1 / (float) Src->pow2Width; - right = (float) srect->x2 / (float) Src->pow2Width; + left = srect->x1; + right = srect->x2; if(upsidedown) { - top = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height; - bottom = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height; + top = Src->currentDesc.Height - srect->y1; + bottom = Src->currentDesc.Height - srect->y2; } else { - top = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height; - bottom = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height; + top = Src->currentDesc.Height - srect->y2; + bottom = Src->currentDesc.Height - srect->y1; + } + + if(Src->Flags & SFLAG_NORMCOORD) { + left /= Src->pow2Width; + right /= Src->pow2Width; + top /= Src->pow2Height; + bottom /= Src->pow2Height; } /* draw the source texture stretched and upside down. The correct surface is bound already */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP); glDrawBuffer(drawBuffer); glReadBuffer(drawBuffer); @@ -2735,21 +3027,42 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glEnd(); checkGLcall("glEnd and previous"); + if(texture_target != This->glDescription.target) { + glDisable(texture_target); + glEnable(This->glDescription.target); + texture_target = This->glDescription.target; + } + /* Now read the stretched and upside down image into the destination texture */ - glBindTexture(This->glDescription.target, This->glDescription.textureName); + glBindTexture(texture_target, This->glDescription.textureName); checkGLcall("glBindTexture"); - glCopyTexSubImage2D(This->glDescription.target, + glCopyTexSubImage2D(texture_target, 0, drect->x1, drect->y1, /* xoffset, yoffset */ 0, 0, /* We blitted the image to the origin */ drect->x2 - drect->x1, drect->y2 - drect->y1); checkGLcall("glCopyTexSubImage2D"); - /* Write the back buffer backup back */ - glBindTexture(GL_TEXTURE_2D, backup ? backup : Src->glDescription.textureName); - checkGLcall("glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName)"); - if(drawBuffer == GL_BACK) { + /* Write the back buffer backup back */ + if(backup) { + if(texture_target != GL_TEXTURE_2D) { + glDisable(texture_target); + glEnable(GL_TEXTURE_2D); + texture_target = GL_TEXTURE_2D; + } + glBindTexture(GL_TEXTURE_2D, backup); + checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)"); + } else { + if(texture_target != Src->glDescription.target) { + glDisable(texture_target); + glEnable(Src->glDescription.target); + texture_target = Src->glDescription.target; + } + glBindTexture(Src->glDescription.target, Src->glDescription.textureName); + checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)"); + } + glBegin(GL_QUADS); /* top left */ glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height); @@ -2771,6 +3084,8 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* Restore the old draw buffer */ glDrawBuffer(GL_BACK); } + glDisable(texture_target); + checkGLcall("glDisable(texture_target)"); /* Cleanup */ if(src != Src->glDescription.textureName && src != backup) { @@ -2781,6 +3096,7 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glDeleteTextures(1, &backup); checkGLcall("glDeleteTextures(1, &backup)"); } + LEAVE_GL(); } @@ -2936,16 +3252,27 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * TRACE("Unsupported blit between buffers on the same swapchain\n"); return WINED3DERR_INVALIDCALL; - } else if((dstSwapchain || This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) && - (srcSwapchain || SrcSurface == myDevice->render_targets[0]) ) { - ERR("Can't perform hardware blit between 2 different swapchains, falling back to software\n"); + } else if(dstSwapchain && dstSwapchain == srcSwapchain) { + FIXME("Implement hardware blit between two surfaces on the same swapchain\n"); + return WINED3DERR_INVALIDCALL; + } 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]) { + 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]) { + FIXME("Implement blit from a swapchain to the active render target\n"); return WINED3DERR_INVALIDCALL; } - if(srcSwapchain || SrcSurface == myDevice->render_targets[0]) { + if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) { /* Blit from render target to texture */ WINED3DRECT srect; BOOL upsideDown, stretchx; + BOOL paletteOverride = FALSE; if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { TRACE("Color keying not supported by frame buffer to texture blit\n"); @@ -2981,10 +3308,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * rect.x1 = tmp; upsideDown = !upsideDown; } - if(!srcSwapchain) { - TRACE("Reading from an offscreen target\n"); - upsideDown = !upsideDown; - } if(rect.x2 - rect.x1 != srect.x2 - srect.x1) { stretchx = TRUE; @@ -2992,6 +3315,14 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * 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 == WINED3DFMT_P8) && (This->palette == NULL)) { + 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. * @@ -3019,6 +3350,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, 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; @@ -3036,8 +3371,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* Blit from offscreen surface to render target */ float glTexCoord[4]; DWORD oldCKeyFlags = Src->CKeyFlags; - WINEDDCOLORKEY oldBltCKey = This->SrcBltCKey; + WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey; RECT SourceRectangle; + BOOL paletteOverride = FALSE; TRACE("Blt from surface %p to rendertarget %p\n", Src, This); @@ -3053,6 +3389,31 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * 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 == WINED3DFMT_P8) && (Src->palette == NULL)) { + 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 && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) && + (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) == 0) { + 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; + 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, @@ -3073,7 +3434,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * } else if(Flags & WINEDDBLT_KEYSRCOVERRIDE) { /* Use color key from DDBltFx */ Src->CKeyFlags |= WINEDDSD_CKSRCBLT; - This->SrcBltCKey = DDBltFx->ddckSrcColorkey; + Src->SrcBltCKey = DDBltFx->ddckSrcColorkey; } else { /* Do not use color key */ Src->CKeyFlags &= ~WINEDDSD_CKSRCBLT; @@ -3082,35 +3443,38 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* Now load the surface */ IWineD3DSurface_PreLoad((IWineD3DSurface *) Src); - /* Activate the destination context, set it up for blitting */ ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); - ENTER_GL(); - if(!dstSwapchain) { - TRACE("Drawing to offscreen buffer\n"); - glDrawBuffer(myDevice->offscreenBuffer); - checkGLcall("glDrawBuffer"); - } else { - GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *)This, (IWineD3DSwapChain *)dstSwapchain); - TRACE("Drawing to %#x buffer\n", buffer); - glDrawBuffer(buffer); - checkGLcall("glDrawBuffer"); + 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; } + ENTER_GL(); + myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format, + Src->glDescription.target, Src->pow2Width, Src->pow2Height); + /* Bind the texture */ - glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName); + glBindTexture(Src->glDescription.target, Src->glDescription.textureName); checkGLcall("glBindTexture"); /* Filtering for StretchRect */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - stateLookup[WINELOOKUP_MAGFILTER][Filter - minLookup[WINELOOKUP_MAGFILTER]]); + glTexParameteri(Src->glDescription.target, GL_TEXTURE_MAG_FILTER, + magLookup[Filter - WINED3DTEXF_NONE]); checkGLcall("glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + glTexParameteri(Src->glDescription.target, GL_TEXTURE_MIN_FILTER, minMipLookup[Filter][WINED3DTEXF_NONE]); checkGLcall("glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); checkGLcall("glTexEnvi"); @@ -3118,7 +3482,14 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { glEnable(GL_ALPHA_TEST); checkGLcall("glEnable GL_ALPHA_TEST"); - glAlphaFunc(GL_NOTEQUAL, 0.0); + + /* 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.0); + else + glAlphaFunc(GL_NOTEQUAL, 0.0); checkGLcall("glAlphaFunc\n"); } else { glDisable(GL_ALPHA_TEST); @@ -3155,36 +3526,30 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * checkGLcall("glDisable(GL_ALPHA_TEST)"); } - /* Flush in case the drawable is used by multiple GL contexts */ - if(dstSwapchain && (dstSwapchain->num_contexts >= 2)) - glFlush(); + glBindTexture(Src->glDescription.target, 0); + checkGLcall("glBindTexture(Src->glDescription.target, 0)"); + /* Leave the opengl state valid for blitting */ + myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice); - /* Unbind the texture */ - glBindTexture(GL_TEXTURE_2D, 0); - checkGLcall("glEnable glBindTexture"); - - /* The draw buffer should only need to be restored if we were drawing to the front buffer, and there is a back buffer. - * otherwise the context manager should choose between GL_BACK / offscreenDrawBuffer - */ - if(dstSwapchain && This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer && dstSwapchain->backBuffer) { - glDrawBuffer(GL_BACK); - checkGLcall("glDrawBuffer"); - } /* Restore the color key parameters */ Src->CKeyFlags = oldCKeyFlags; - This->SrcBltCKey = oldBltCKey; + 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; LEAVE_GL(); + /* Flush in case the drawable is used by multiple GL contexts */ + if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2)) + glFlush(); + /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */ /* 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); - /* TODO: This should be moved to ModifyLocation() */ - if(!(dstSwapchain || wined3d_settings.offscreen_rendering_mode != ORM_FBO)) { - This->Flags |= SFLAG_INTEXTURE; - } return WINED3D_OK; } else { @@ -3195,17 +3560,31 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * 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 == WINED3DFMT_P8) { + DWORD alpha; + + if (primary_render_target_is_p8(myDevice)) alpha = DDBltFx->u5.dwFillColor << 24; + else alpha = 0xFF000000; + if (This->palette) { - color = ((0xFF000000) | + 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 = 0xFF000000; + color = alpha; } } else if (This->resource.format == WINED3DFMT_R5G6B5) { @@ -3230,39 +3609,12 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * return WINED3DERR_INVALIDCALL; } - TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice); - if(dstSwapchain && dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]) { - glDrawBuffer(GL_BACK); - checkGLcall("glDrawBuffer(GL_BACK)"); - } else if (dstSwapchain && This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer) { - glDrawBuffer(GL_FRONT); - checkGLcall("glDrawBuffer(GL_FRONT)"); - } else if(This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) { - glDrawBuffer(myDevice->offscreenBuffer); - checkGLcall("glDrawBuffer(myDevice->offscreenBuffer3)"); - } else { - TRACE("Surface is higher back buffer, falling back to software\n"); - return WINED3DERR_INVALIDCALL; - } - TRACE("(%p) executing Render Target override, color = %x\n", This, color); - - IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice, - 1 /* Number of rectangles */, - &rect, - WINED3DCLEAR_TARGET, - color, - 0.0 /* Z */, - 0 /* Stencil */); - - /* Restore the original draw buffer */ - if(!dstSwapchain) { - glDrawBuffer(myDevice->offscreenBuffer); - } else if(dstSwapchain->backBuffer && dstSwapchain->backBuffer[0]) { - glDrawBuffer(GL_BACK); - } - vcheckGLcall("glDrawBuffer"); - + IWineD3DDeviceImpl_ClearSurface(myDevice, This, + 1, /* Number of rectangles */ + &rect, WINED3DCLEAR_TARGET, color, + 0.0 /* Z */, + 0 /* Stencil */); return WINED3D_OK; } } @@ -3317,6 +3669,12 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *Dest 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)); + if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED))) + { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return WINEDDERR_SURFACEBUSY; + } + /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair, * except depth blits, which seem to work */ @@ -3349,6 +3707,12 @@ HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, D IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans); + if ( (This->Flags & SFLAG_LOCKED) || ((srcImpl != NULL) && (srcImpl->Flags & SFLAG_LOCKED))) + { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return WINEDDERR_SURFACEBUSY; + } + if(myDevice->inScene && (iface == myDevice->stencilBufferTarget || (Source && Source == myDevice->stencilBufferTarget))) { @@ -3397,6 +3761,66 @@ HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, D return IWineD3DBaseSurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans); } +HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + RGBQUAD col[256]; + IWineD3DPaletteImpl *pal = This->palette; + unsigned int n; + TRACE("(%p)\n", This); + + if (!pal) return WINED3D_OK; + + if(This->resource.format == WINED3DFMT_P8 || + This->resource.format == WINED3DFMT_A8P8) + { + 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 || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX); + + /* 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, This->srgb); + + if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION)) + { + /* 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 */ + d3dfmt_p8_upload_palette(iface, convert); + } else { + if(!(This->Flags & SFLAG_INSYSMEM)) { + TRACE("Palette changed with surface that does not have an up to date system memory copy\n"); + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + } + TRACE("Dirtifying surface\n"); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + } + } + + if(This->Flags & SFLAG_DIBSECTION) { + TRACE("(%p): Updating the hdc's palette\n", This); + for (n=0; n<256; n++) { + col[n].rgbRed = pal->palents[n].peRed; + col[n].rgbGreen = pal->palents[n].peGreen; + col[n].rgbBlue = pal->palents[n].peBlue; + col[n].rgbReserved = 0; + } + SetDIBColorTable(This->hDC, 0, 256, col); + } + + /* Propagate the changes to the drawable when we have a palette. */ + if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) + IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, NULL); + + return WINED3D_OK; +} + static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { /** Check against the maximum texture sizes supported by the video card **/ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; @@ -3413,7 +3837,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { This->glDescription.target = GL_TEXTURE_2D; /* Non-power2 support */ - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) { pow2Width = This->currentDesc.Width; pow2Height = This->currentDesc.Height; } else { @@ -3429,7 +3853,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { WINED3DFORMAT Format = This->resource.format; /** TODO: add support for non power two compressed textures **/ if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 - || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) { + || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5 + || This->resource.format == WINED3DFMT_ATI2N) { FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n", This, This->currentDesc.Width, This->currentDesc.Height); return WINED3DERR_NOTAVAILABLE; @@ -3458,6 +3883,20 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { 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 + 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. + */ + if(This->Flags & SFLAG_NONPOW2 && GL_SUPPORT(ARB_TEXTURE_RECTANGLE) && + !((This->resource.format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) && (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX))) + { + This->glDescription.target = GL_TEXTURE_RECTANGLE_ARB; + This->pow2Width = This->currentDesc.Width; + 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; @@ -3466,20 +3905,165 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { 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; + } + } + This->Flags |= SFLAG_INSYSMEM; return WINED3D_OK; } +void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + + TRACE("(%p) New location %#x\n", This, location); + + if (location & ~SFLAG_DS_LOCATIONS) { + FIXME("(%p) Invalid location (%#x) specified\n", This, location); + } + + This->Flags &= ~SFLAG_DS_LOCATIONS; + This->Flags |= location; +} + +void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + TRACE("(%p) New location %#x\n", This, 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 (This->current_renderbuffer) { + FIXME("(%p) Not supported with fixed up depth stencil\n", This); + return; + } + + if (location == SFLAG_DS_OFFSCREEN) { + if (This->Flags & SFLAG_DS_ONSCREEN) { + GLint old_binding = 0; + + TRACE("(%p) Copying onscreen depth buffer to depth texture\n", This); + + ENTER_GL(); + + if (!device->depth_blt_texture) { + glGenTextures(1, &device->depth_blt_texture); + } + + /* Note that we use depth_blt here as well, rather than glCopyTexImage2D + * directly on the FBO texture. That's because we need to flip. */ + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); + glBindTexture(GL_TEXTURE_2D, device->depth_blt_texture); + glCopyTexImage2D(This->glDescription.target, + This->glDescription.level, + This->glDescription.glFormatInternal, + 0, + 0, + This->currentDesc.Width, + This->currentDesc.Height, + 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); + glBindTexture(GL_TEXTURE_2D, old_binding); + + /* Setup the destination */ + if (!device->depth_blt_rb) { + GL_EXTCALL(glGenRenderbuffersEXT(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_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, device->depth_blt_rb)); + checkGLcall("glBindRenderbufferEXT"); + GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, 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; + } + + context_bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->dst_fbo); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, device->depth_blt_rb)); + checkGLcall("glFramebufferRenderbufferEXT"); + context_attach_depth_stencil_fbo(device, GL_FRAMEBUFFER_EXT, iface, FALSE); + + /* Do the actual blit */ + depth_blt((IWineD3DDevice *)device, device->depth_blt_texture, This->currentDesc.Width, This->currentDesc.Height); + checkGLcall("depth_blt"); + + if (device->activeContext->current_fbo) { + context_bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->current_fbo->id); + } else { + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glBindFramebuffer()"); + } + + LEAVE_GL(); + } else { + FIXME("No up to date depth stencil location\n"); + } + } 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(); + + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glBindFramebuffer()"); + depth_blt((IWineD3DDevice *)device, This->glDescription.textureName, This->currentDesc.Width, This->currentDesc.Height); + checkGLcall("depth_blt"); + + if (device->activeContext->current_fbo) { + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->activeContext->current_fbo->id)); + checkGLcall("glBindFramebuffer()"); + } + + LEAVE_GL(); + } else { + FIXME("No up to date depth stencil location\n"); + } + } else { + ERR("(%p) Invalid location (%#x) specified\n", This, location); + } + + This->Flags |= location; +} + static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DBaseTexture *texture; + IWineD3DSurfaceImpl *overlay; TRACE("(%p)->(%s, %s)\n", iface, flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE", persistent ? "TRUE" : "FALSE"); - /* TODO: For offscreen textures with fbo offscreen rendering the drawable is the same as the texture.*/ + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + IWineD3DSwapChain *swapchain = NULL; + + if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { + TRACE("Surface %p is an onscreen surface\n", iface); + + IWineD3DSwapChain_Release(swapchain); + } else { + /* 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); + } + } + if(persistent) { if((This->Flags & SFLAG_INTEXTURE) && !(flag & SFLAG_INTEXTURE)) { if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) { @@ -3490,6 +4074,13 @@ static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DW } This->Flags &= ~SFLAG_LOCATIONS; This->Flags |= flag; + + /* Redraw emulated overlays, if any */ + if(flag & SFLAG_INDRAWABLE && !list_empty(&This->overlays)) { + LIST_FOR_EACH_ENTRY(overlay, &This->overlays, IWineD3DSurfaceImpl, overlay_entry) { + IWineD3DSurface_DrawOverlay((IWineD3DSurface *) overlay); + } + } } else { if((This->Flags & SFLAG_INTEXTURE) && (flag & SFLAG_INTEXTURE)) { if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) { @@ -3503,13 +4094,14 @@ static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DW } struct coords { - int x, y, z; + GLfloat x, y, z; }; static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) { struct coords coords[4]; RECT rect; IWineD3DSwapChain *swapchain = NULL; + IWineD3DBaseTexture *texture = NULL; HRESULT hr; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; @@ -3522,10 +4114,38 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT rect.bottom = This->currentDesc.Height; } - ActivateContext(device, device->render_targets[0], CTXUSAGE_BLIT); + ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); ENTER_GL(); - if(This->glDescription.target == GL_TEXTURE_2D) { + if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) { + glEnable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)"); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName); + checkGLcall("GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName)"); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + checkGLcall("glTexParameteri"); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + checkGLcall("glTexParameteri"); + + coords[0].x = rect.left; + coords[0].z = 0; + + coords[1].x = rect.left; + coords[1].z = 0; + + coords[2].x = rect.right; + coords[2].z = 0; + + coords[3].x = rect.right; + coords[3].z = 0; + + coords[0].y = rect.top; + coords[1].y = rect.bottom; + coords[2].y = rect.bottom; + coords[3].y = rect.top; + } else if(This->glDescription.target == GL_TEXTURE_2D) { + glEnable(GL_TEXTURE_2D); + checkGLcall("glEnable(GL_TEXTURE_2D)"); glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName); checkGLcall("GL_TEXTURE_2D, This->glDescription.textureName)"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -3533,26 +4153,24 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLcall("glTexParameteri"); - coords[0].x = rect.left / This->pow2Width; + coords[0].x = (float)rect.left / This->pow2Width; coords[0].z = 0; - coords[1].x = rect.left / This->pow2Width; + coords[1].x = (float)rect.left / This->pow2Width; coords[1].z = 0; - coords[2].x = rect.right / This->pow2Width; + coords[2].x = (float)rect.right / This->pow2Width; coords[2].z = 0; - coords[3].x = rect.right / This->pow2Width; + coords[3].x = (float)rect.right / This->pow2Width; coords[3].z = 0; - coords[0].y = rect.top / This->pow2Height; - coords[1].y = rect.bottom / This->pow2Height; - coords[2].y = rect.bottom / This->pow2Height; - coords[3].y = rect.top / This->pow2Height; + coords[0].y = (float)rect.top / This->pow2Height; + coords[1].y = (float)rect.bottom / This->pow2Height; + coords[2].y = (float)rect.bottom / This->pow2Height; + coords[3].y = (float)rect.top / This->pow2Height; } else { /* Must be a cube map */ - glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable(GL_TEXTURE_2D)"); glEnable(GL_TEXTURE_CUBE_MAP_ARB); checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)"); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName); @@ -3603,6 +4221,7 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT coords[1].x = 1; coords[1].y = -1; coords[1].z = -1; coords[2].x = 1; coords[2].y = -1; coords[2].z = -1; coords[3].x = -1; coords[3].y = -1; coords[3].z = -1; + break; default: ERR("Unexpected texture target\n"); @@ -3612,36 +4231,49 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT } glBegin(GL_QUADS); - glTexCoord3iv((GLint *) &coords[0]); + glTexCoord3fv(&coords[0].x); glVertex2i(rect.left, device->render_offscreen ? rect.bottom : rect.top); - glTexCoord3iv((GLint *) &coords[1]); - glVertex2i(0, device->render_offscreen ? rect.top : rect.bottom); + glTexCoord3fv(&coords[1].x); + glVertex2i(rect.left, device->render_offscreen ? rect.top : rect.bottom); - glTexCoord3iv((GLint *) &coords[2]); + glTexCoord3fv(&coords[2].x); glVertex2i(rect.right, device->render_offscreen ? rect.top : rect.bottom); - glTexCoord3iv((GLint *) &coords[3]); + glTexCoord3fv(&coords[3].x); glVertex2i(rect.right, device->render_offscreen ? rect.bottom : rect.top); glEnd(); checkGLcall("glEnd"); if(This->glDescription.target != GL_TEXTURE_2D) { - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable(GL_TEXTURE_2D)"); glDisable(GL_TEXTURE_CUBE_MAP_ARB); checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } else { + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); } + LEAVE_GL(); hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DSwapChain, (void **) &swapchain); if(hr == WINED3D_OK && swapchain) { /* Make sure to flush the buffers. This is needed in apps like Red Alert II and Tiberian SUN that use multiple WGL contexts. */ - if(((IWineD3DSwapChainImpl*)swapchain)->num_contexts >= 2) + if(((IWineD3DSwapChainImpl*)swapchain)->frontBuffer == (IWineD3DSurface*)This || + ((IWineD3DSwapChainImpl*)swapchain)->num_contexts >= 2) glFlush(); IWineD3DSwapChain_Release(swapchain); + } else { + /* We changed the filtering settings on the texture. Inform the container about this to get the filters + * reset properly next draw + */ + hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DBaseTexture, (void **) &texture); + if(hr == WINED3D_OK && texture) { + ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; + ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; + ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE; + IWineD3DBaseTexture_Release(texture); + } } - LEAVE_GL(); } /***************************************************************************** @@ -3650,9 +4282,9 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT * Copies the current surface data from wherever it is to the requested * location. The location is one of the surface flags, SFLAG_INSYSMEM, * SFLAG_INTEXTURE and SFLAG_INDRAWABLE. When the surface is current in - * multiple locations, the gl texture is prefered over the drawable, which is - * prefered over system memory. The PBO counts as system memory. If rect is - * not NULL, only the specified rectangle is copied(only supported for + * multiple locations, the gl texture is preferred over the drawable, which is + * preferred over system memory. The PBO counts as system memory. If rect is + * not NULL, only the specified rectangle is copied (only supported for * sysmem<->drawable copies at the moment). If rect is NULL, the destination * location is marked up to date after the copy. * @@ -3668,12 +4300,25 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + IWineD3DSwapChain *swapchain = NULL; GLenum format, internal, type; CONVERT_TYPES convert; int bpp; int width, pitch, outpitch; BYTE *mem; + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { + TRACE("Surface %p is an onscreen surface\n", iface); + + IWineD3DSwapChain_Release(swapchain); + } else { + /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. + * Prefer SFLAG_INTEXTURE. */ + if (flag == SFLAG_INDRAWABLE) flag = SFLAG_INTEXTURE; + } + } + TRACE("(%p)->(%s, %p)\n", iface, flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE", rect); @@ -3681,7 +4326,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D TRACE("Rectangle: (%d,%d)-(%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom); } - /* TODO: For fbo targets, texture == drawable */ if(This->Flags & flag) { TRACE("Location already up to date\n"); return WINED3D_OK; @@ -3698,6 +4342,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D /* Download the surface to system memory */ if(This->Flags & SFLAG_INTEXTURE) { + if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + surface_bind_and_dirtify(This); + surface_download_data(This); } else { read_from_framebuffer(This, rect, @@ -3708,41 +4355,55 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D if(This->Flags & SFLAG_INTEXTURE) { surface_blt_to_drawable(This, rect); } else { - flush_to_framebuffer_drawpixels(This); - } - } else /* if(flag == SFLAG_INTEXTURE) */ { - d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb); + d3dfmt_get_conv(This, TRUE /* We need color keying */, FALSE /* We won't use textures */, &format, &internal, &type, &convert, &bpp, This->srgb); - if (This->Flags & SFLAG_INDRAWABLE) { - GLint prevRead; + /* The width is in 'length' not in bytes */ + width = This->currentDesc.Width; + pitch = IWineD3DSurface_GetPitch(iface); - ENTER_GL(); - glGetIntegerv(GL_READ_BUFFER, &prevRead); - vcheckGLcall("glGetIntegerv"); - glReadBuffer(This->resource.wineD3DDevice->offscreenBuffer); - vcheckGLcall("glReadBuffer"); - - if(!(This->Flags & SFLAG_ALLOCATED)) { - surface_allocate_surface(This, internal, This->pow2Width, - This->pow2Height, format, type); + /* 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)) { + TRACE("Removing the pbo attached to surface %p\n", This); + surface_remove_pbo(This); } - clear_unused_channels(This); + if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { + int height = This->currentDesc.Height; - glCopyTexSubImage2D(This->glDescription.target, - This->glDescription.level, - 0, 0, 0, 0, - This->currentDesc.Width, - This->currentDesc.Height); - checkGLcall("glCopyTexSubImage2D"); + /* Stick to the alignment for the converted surface too, makes it easier to load the surface */ + outpitch = width * bpp; + outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1); - glReadBuffer(prevRead); - vcheckGLcall("glReadBuffer"); + mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height); + if(!mem) { + ERR("Out of memory %d, %d!\n", outpitch, height); + return WINED3DERR_OUTOFVIDEOMEMORY; + } + d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This); - LEAVE_GL(); + This->Flags |= SFLAG_CONVERTED; + } else { + This->Flags &= ~SFLAG_CONVERTED; + mem = This->resource.allocatedMemory; + } + + flush_to_framebuffer_drawpixels(This, format, type, bpp, mem); + + /* Don't delete PBO memory */ + if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO)) + HeapFree(GetProcessHeap(), 0, mem); + } + } else /* if(flag == SFLAG_INTEXTURE) */ { + if (This->Flags & SFLAG_INDRAWABLE) { + read_from_framebuffer_texture(This); + } else { /* Upload from system memory */ + d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb); + + if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + surface_bind_and_dirtify(This); + ENTER_GL(); - TRACE("Updated target %d\n", This->glDescription.target); - } else { /* The only place where LoadTexture() might get called when isInDraw=1 * is ActivateContext where lastActiveRenderTarget is preloaded. */ @@ -3761,6 +4422,13 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D width = This->currentDesc.Width; pitch = IWineD3DSurface_GetPitch(iface); + /* 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)) { + TRACE("Removing the pbo attached to surface %p\n", This); + surface_remove_pbo(This); + } + if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { int height = This->currentDesc.Height; @@ -3810,6 +4478,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D /* Restore the default pitch */ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + LEAVE_GL(); /* Don't delete PBO memory */ if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO)) @@ -3821,9 +4490,63 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D This->Flags |= flag; } + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !swapchain + && (This->Flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE))) { + /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */ + This->Flags |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE); + } + return WINED3D_OK; } +HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + IWineD3DSwapChain *swapchain = NULL; + + /* Update the drawable size method */ + if(container) { + IWineD3DBase_QueryInterface(container, &IID_IWineD3DSwapChain, (void **) &swapchain); + } + if(swapchain) { + This->get_drawable_size = get_drawable_size_swapchain; + IWineD3DSwapChain_Release(swapchain); + } 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; + } + } + + return IWineD3DBaseSurfaceImpl_SetContainer(iface, container); +} + +static WINED3DSURFTYPE WINAPI IWineD3DSurfaceImpl_GetImplType(IWineD3DSurface *iface) { + return SURFACE_OPENGL; +} + +static HRESULT WINAPI IWineD3DSurfaceImpl_DrawOverlay(IWineD3DSurface *iface) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + HRESULT hr; + + /* If there's no destination surface there is nothing to do */ + if(!This->overlay_dest) return WINED3D_OK; + + /* Blt calls ModifyLocation on the dest surface, which in turn calls DrawOverlay to + * update the overlay. Prevent an endless recursion + */ + if(This->overlay_dest->Flags & SFLAG_INOVERLAYDRAW) { + return WINED3D_OK; + } + This->overlay_dest->Flags |= SFLAG_INOVERLAYDRAW; + hr = IWineD3DSurfaceImpl_Blt((IWineD3DSurface *) This->overlay_dest, &This->overlay_destrect, + iface, &This->overlay_srcrect, WINEDDBLT_WAIT, + NULL, WINED3DTEXF_LINEAR); + This->overlay_dest->Flags &= ~SFLAG_INOVERLAYDRAW; + + return hr; +} + const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = { /* IUnknown */ @@ -3839,6 +4562,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DBaseSurfaceImpl_SetPriority, IWineD3DBaseSurfaceImpl_GetPriority, IWineD3DSurfaceImpl_PreLoad, + IWineD3DSurfaceImpl_UnLoad, IWineD3DBaseSurfaceImpl_GetType, /* IWineD3DSurface */ IWineD3DBaseSurfaceImpl_GetContainer, @@ -3856,7 +4580,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_BltFast, IWineD3DBaseSurfaceImpl_GetPalette, IWineD3DBaseSurfaceImpl_SetPalette, - IWineD3DBaseSurfaceImpl_RealizePalette, + IWineD3DSurfaceImpl_RealizePalette, IWineD3DBaseSurfaceImpl_SetColorKey, IWineD3DBaseSurfaceImpl_GetPitch, IWineD3DSurfaceImpl_SetMem, @@ -3871,12 +4595,52 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_LoadTexture, IWineD3DSurfaceImpl_BindTexture, IWineD3DSurfaceImpl_SaveSnapshot, - IWineD3DBaseSurfaceImpl_SetContainer, + IWineD3DSurfaceImpl_SetContainer, IWineD3DSurfaceImpl_SetGlTextureDesc, IWineD3DSurfaceImpl_GetGlDesc, IWineD3DSurfaceImpl_GetData, IWineD3DSurfaceImpl_SetFormat, IWineD3DSurfaceImpl_PrivateSetup, IWineD3DSurfaceImpl_ModifyLocation, - IWineD3DSurfaceImpl_LoadLocation + IWineD3DSurfaceImpl_LoadLocation, + IWineD3DSurfaceImpl_GetImplType, + IWineD3DSurfaceImpl_DrawOverlay +}; +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION device->adapter->gl_info +static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +static void ffp_blit_free(IWineD3DDevice *iface) { } + +static HRESULT ffp_blit_set(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height) { + glEnable(textype); + checkGLcall("glEnable(textype)"); + return WINED3D_OK; +} + +static void ffp_blit_unset(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } +} + +static BOOL ffp_blit_conv_supported(WINED3DFORMAT fmt) { + TRACE("Checking blit format support for format %s: [FAILED]\n", debug_d3dformat(fmt)); + return FALSE; +} + +const struct blit_shader ffp_blit = { + ffp_blit_alloc, + ffp_blit_free, + ffp_blit_set, + ffp_blit_unset, + ffp_blit_conv_supported }; diff --git a/reactos/dll/directx/wine/wined3d/surface_base.c b/reactos/dll/directx/wine/wined3d/surface_base.c index f57b9f49ee3..841ca80cd1b 100644 --- a/reactos/dll/directx/wine/wined3d/surface_base.c +++ b/reactos/dll/directx/wine/wined3d/surface_base.c @@ -7,7 +7,7 @@ * Copyright 2002-2003 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber - * Copyright 2006-2007 Stefan Dösinger for CodeWeavers + * Copyright 2006-2008 Stefan Dösinger for CodeWeavers * Copyright 2007 Henri Verbeet * Copyright 2006-2007 Roderick Colenbrander * @@ -34,6 +34,57 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); +/* See also float_16_to_32() in wined3d_private.h */ +static inline unsigned short float_32_to_16(const float *in) +{ + int exp = 0; + float tmp = fabs(*in); + unsigned int mantissa; + unsigned short ret; + + /* Deal with special numbers */ + if(*in == 0.0) return 0x0000; + if(isnan(*in)) return 0x7C01; + if(!finite(*in)) return (*in < 0.0 ? 0xFC00 : 0x7c00); + + if(tmp < pow(2, 10)) { + do + { + tmp = tmp * 2.0; + exp--; + }while(tmp < pow(2, 10)); + } else if(tmp >= pow(2, 11)) { + do + { + tmp /= 2.0; + exp++; + }while(tmp >= pow(2, 11)); + } + + mantissa = (unsigned int) tmp; + if(tmp - mantissa >= 0.5) mantissa++; /* round to nearest, away from zero */ + + exp += 10; /* Normalize the mantissa */ + exp += 15; /* Exponent is encoded with excess 15 */ + + if(exp > 30) { /* too big */ + ret = 0x7c00; /* INF */ + } else if(exp <= 0) { + /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */ + while(exp <= 0) { + mantissa = mantissa >> 1; + exp++; + } + ret = mantissa & 0x3ff; + } else { + ret = (exp << 10) | (mantissa & 0x3ff); + } + + ret |= ((*in < 0.0 ? 1 : 0) << 15); /* Add the sign */ + return ret; +} + + /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */ /* ******************************************* @@ -197,30 +248,25 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal; TRACE("(%p)->(%p)\n", This, Pal); + if(This->palette == PalImpl) { + TRACE("Nop palette change\n"); + return WINED3D_OK; + } + if(This->palette != NULL) if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE; - if(PalImpl != NULL) { - if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { - /* Set the device's main palette if the palette - * wasn't a primary palette before - */ - if(!(PalImpl->Flags & WINEDDPCAPS_PRIMARYSURFACE)) { - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - unsigned int i; - - for(i=0; i < 256; i++) { - device->palettes[device->currentPalette][i] = PalImpl->palents[i]; - } - } - - (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE; - } - } This->palette = PalImpl; - return IWineD3DSurface_RealizePalette(iface); + if(PalImpl != NULL) { + if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { + (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE; + } + + return IWineD3DSurface_RealizePalette(iface); + } + else return WINED3D_OK; } HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, WINEDDCOLORKEY *CKey) { @@ -287,45 +333,6 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD return WINED3D_OK; } -HRESULT WINAPI IWineD3DBaseSurfaceImpl_RealizePalette(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - RGBQUAD col[256]; - IWineD3DPaletteImpl *pal = This->palette; - unsigned int n; - TRACE("(%p)\n", This); - - if(This->resource.format == WINED3DFMT_P8 || - This->resource.format == WINED3DFMT_A8P8) - { - if(!This->Flags & SFLAG_INSYSMEM) { - FIXME("Palette changed with surface that does not have an up to date system memory copy\n"); - } - TRACE("Dirtifying surface\n"); - IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); - } - - if(This->Flags & SFLAG_DIBSECTION) { - TRACE("(%p): Updating the hdc's palette\n", This); - for (n=0; n<256; n++) { - if(pal) { - col[n].rgbRed = pal->palents[n].peRed; - col[n].rgbGreen = pal->palents[n].peGreen; - col[n].rgbBlue = pal->palents[n].peBlue; - } else { - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - /* Use the default device palette */ - col[n].rgbRed = device->palettes[device->currentPalette][n].peRed; - col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen; - col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue; - } - col[n].rgbReserved = 0; - } - SetDIBColorTable(This->hDC, 0, 256, col); - } - - return WINED3D_OK; -} - DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; DWORD ret; @@ -350,8 +357,9 @@ DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) { HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + LONG w, h; - FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y); + TRACE("(%p)->(%d,%d) Stub!\n", This, X, Y); if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) { @@ -359,21 +367,40 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface return WINEDDERR_NOTAOVERLAYSURFACE; } + w = This->overlay_destrect.right - This->overlay_destrect.left; + h = This->overlay_destrect.bottom - This->overlay_destrect.top; + This->overlay_destrect.left = X; + This->overlay_destrect.top = Y; + This->overlay_destrect.right = X + w; + This->overlay_destrect.bottom = Y + h; + + IWineD3DSurface_DrawOverlay(iface); + return WINED3D_OK; } HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + HRESULT hr; - FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y); + TRACE("(%p)->(%p,%p)\n", This, X, Y); if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) { TRACE("(%p): Not an overlay surface\n", This); return WINEDDERR_NOTAOVERLAYSURFACE; } + if(This->overlay_dest == NULL) { + *X = 0; *Y = 0; + hr = WINEDDERR_OVERLAYNOTVISIBLE; + } else { + *X = This->overlay_destrect.left; + *Y = This->overlay_destrect.top; + hr = WINED3D_OK; + } - return WINED3D_OK; + TRACE("Returning 0x%08x, position %d, %d\n", hr, *X, *Y); + return hr; } HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) { @@ -394,14 +421,55 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *ifac HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface; - FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX); + TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX); if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) { - TRACE("(%p): Not an overlay surface\n", This); + WARN("(%p): Not an overlay surface\n", This); return WINEDDERR_NOTAOVERLAYSURFACE; + } else if(!DstSurface) { + WARN("(%p): Dest surface is NULL\n", This); + return WINED3DERR_INVALIDCALL; } + if(SrcRect) { + This->overlay_srcrect = *SrcRect; + } else { + This->overlay_srcrect.left = 0; + This->overlay_srcrect.top = 0; + This->overlay_srcrect.right = This->currentDesc.Width; + This->overlay_srcrect.bottom = This->currentDesc.Height; + } + + if(DstRect) { + This->overlay_destrect = *DstRect; + } else { + This->overlay_destrect.left = 0; + This->overlay_destrect.top = 0; + This->overlay_destrect.right = Dst ? Dst->currentDesc.Width : 0; + This->overlay_destrect.bottom = Dst ? Dst->currentDesc.Height : 0; + } + + if(This->overlay_dest && (This->overlay_dest != Dst || Flags & WINEDDOVER_HIDE)) { + list_remove(&This->overlay_entry); + } + + if(Flags & WINEDDOVER_SHOW) { + if(This->overlay_dest != Dst) { + This->overlay_dest = Dst; + list_add_tail(&Dst->overlays, &This->overlay_entry); + } + } else if(Flags & WINEDDOVER_HIDE) { + /* tests show that the rectangles are erased on hide */ + This->overlay_srcrect.left = 0; This->overlay_srcrect.top = 0; + This->overlay_srcrect.right = 0; This->overlay_srcrect.bottom = 0; + This->overlay_destrect.left = 0; This->overlay_destrect.top = 0; + This->overlay_destrect.right = 0; This->overlay_destrect.bottom = 0; + This->overlay_dest = NULL; + } + + IWineD3DSurface_DrawOverlay(iface); + return WINED3D_OK; } @@ -537,7 +605,7 @@ HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) { b_info->bmiHeader.biClrImportant = 0; /* Get the bit masks */ - masks = (DWORD *) &(b_info->bmiColors); + masks = (DWORD *)b_info->bmiColors; switch (This->resource.format) { case WINED3DFMT_R8G8B8: usage = DIB_RGB_COLORS; @@ -589,7 +657,7 @@ HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) { TRACE("DIBSection at : %p\n", This->dib.bitmap_data); /* copy the existing surface to the dib section */ if(This->resource.allocatedMemory) { - memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage); + memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->currentDesc.Height * IWineD3DSurface_GetPitch(iface)); } else { /* This is to make LockRect read the gl Texture although memory is allocated */ This->Flags &= ~SFLAG_INSYSMEM; @@ -614,6 +682,111 @@ HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) { return WINED3D_OK; } +void convert_r32f_r16f(BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) { + unsigned int x, y; + float *src_f; + unsigned short *dst_s; + + TRACE("Converting %dx%d pixels, pitches %d %d\n", w, h, pitch_in, pitch_out); + for(y = 0; y < h; y++) { + src_f = (float *) (src + y * pitch_in); + dst_s = (unsigned short *) (dst + y * pitch_out); + for(x = 0; x < w; x++) { + dst_s[x] = float_32_to_16(src_f + x); + } + } +} + +struct d3dfmt_convertor_desc { + WINED3DFORMAT from, to; + void (*convert)(BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h); +}; + +struct d3dfmt_convertor_desc convertors[] = { + {WINED3DFMT_R32F, WINED3DFMT_R16F, convert_r32f_r16f}, +}; + +static inline struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to) { + unsigned int i; + for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) { + if(convertors[i].from == from && convertors[i].to == to) { + return &convertors[i]; + } + } + return NULL; +} + +/***************************************************************************** + * surface_convert_format + * + * Creates a duplicate of a surface in a different format. Is used by Blt to + * blit between surfaces with different formats + * + * Parameters + * source: Source surface + * fmt: Requested destination format + * + *****************************************************************************/ +IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, WINED3DFORMAT to_fmt) { + IWineD3DSurface *ret = NULL; + struct d3dfmt_convertor_desc *conv; + WINED3DLOCKED_RECT lock_src, lock_dst; + HRESULT hr; + + conv = find_convertor(source->resource.format, to_fmt); + if(!conv) { + FIXME("Cannot find a conversion function from format %s to %s\n", + debug_d3dformat(source->resource.format), debug_d3dformat(to_fmt)); + return NULL; + } + + IWineD3DDevice_CreateSurface((IWineD3DDevice *) source->resource.wineD3DDevice, + source->currentDesc.Width, + source->currentDesc.Height, + to_fmt, + TRUE, /* lockable */ + TRUE, /* discard */ + 0, /* level */ + &ret, + WINED3DRTYPE_SURFACE, + 0, /* usage */ + WINED3DPOOL_SCRATCH, + WINED3DMULTISAMPLE_NONE, /* TODO: Multisampled conversion */ + 0, /* MultiSampleQuality */ + NULL, /* SharedHandle */ + IWineD3DSurface_GetImplType((IWineD3DSurface *) source), + NULL); /* parent */ + if(!ret) { + ERR("Failed to create a destination surface for conversion\n"); + return NULL; + } + + memset(&lock_src, 0, sizeof(lock_src)); + memset(&lock_dst, 0, sizeof(lock_dst)); + + hr = IWineD3DSurface_LockRect((IWineD3DSurface *) source, &lock_src, NULL, WINED3DLOCK_READONLY); + if(FAILED(hr)) { + ERR("Failed to lock the source surface\n"); + IWineD3DSurface_Release(ret); + return NULL; + } + hr = IWineD3DSurface_LockRect(ret, &lock_dst, NULL, WINED3DLOCK_READONLY); + if(FAILED(hr)) { + ERR("Failed to lock the dest surface\n"); + IWineD3DSurface_UnlockRect((IWineD3DSurface *) source); + IWineD3DSurface_Release(ret); + return NULL; + } + + conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch, + source->currentDesc.Width, source->currentDesc.Height); + + IWineD3DSurface_UnlockRect(ret); + IWineD3DSurface_UnlockRect((IWineD3DSurface *) source); + + return (IWineD3DSurfaceImpl *) ret; +} + /***************************************************************************** * _Blt_ColorFill * @@ -651,7 +824,7 @@ static HRESULT case 2: COLORFILL_ROW(WORD) case 3: { - BYTE *d = (BYTE *) buf; + BYTE *d = buf; for (x = 0; x < width; x++,d+=3) { d[0] = (color ) & 0xFF; @@ -738,51 +911,53 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, FIXME("Filters not supported in software blit\n"); } - if (Src == This) + /* 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))) { - IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); - dfmt = This->resource.format; - slock = dlock; - sfmt = dfmt; - sEntry = getFormatDescEntry(sfmt, NULL, NULL); - dEntry = sEntry; + WARN("Application gave us bad source rectangle for Blt.\n"); + return WINEDDERR_INVALIDRECT; } - else + /* 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))) { - if (Src) - { - IWineD3DSurface_LockRect(SrcSurface, &slock, NULL, WINED3DLOCK_READONLY); - sfmt = Src->resource.format; - } - sEntry = getFormatDescEntry(sfmt, NULL, NULL); - dfmt = This->resource.format; - dEntry = getFormatDescEntry(dfmt, NULL, NULL); - IWineD3DSurface_LockRect(iface, &dlock,NULL,0); + WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); + return WINEDDERR_INVALIDRECT; } - if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX; + /* Now handle negative values in the rectangles. Warning: only supported for now + in the 'simple' cases (ie not in any stretching / rotation cases). - if (sEntry->isFourcc && dEntry->isFourcc) + 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)) )) { - if (sfmt != dfmt) - { - FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n"); - ret = WINED3DERR_WRONGTEXTUREFORMAT; - goto release; - } - memcpy(dlock.pBits, slock.pBits, This->resource.size); - goto release; - } - - if (sEntry->isFourcc && !dEntry->isFourcc) - { - FIXME("DXTC decompression not supported right now\n"); - goto release; + TRACE("Nothing to be done !\n"); + return WINED3D_OK; } if (DestRect) { - memcpy(&xdst,DestRect,sizeof(xdst)); + xdst = *DestRect; } else { @@ -794,7 +969,7 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, if (SrcRect) { - memcpy(&xsrc,SrcRect,sizeof(xsrc)); + xsrc = *SrcRect; } else { @@ -811,54 +986,8 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, } } - /* First check for the validity of source / destination rectangles. This was - * verified using a test application + by MSDN. - */ - if ((Src != NULL) && - ((xsrc.bottom > Src->currentDesc.Height) || (xsrc.bottom < 0) || - (xsrc.top > Src->currentDesc.Height) || (xsrc.top < 0) || - (xsrc.left > Src->currentDesc.Width) || (xsrc.left < 0) || - (xsrc.right > Src->currentDesc.Width) || (xsrc.right < 0) || - (xsrc.right < xsrc.left) || (xsrc.bottom < xsrc.top))) - { - WARN("Application gave us bad source rectangle for Blt.\n"); - ret = WINEDDERR_INVALIDRECT; - goto release; - } - /* 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) && - ((xdst.bottom > This->currentDesc.Height) || (xdst.bottom < 0) || - (xdst.top > This->currentDesc.Height) || (xdst.top < 0) || - (xdst.left > This->currentDesc.Width) || (xdst.left < 0) || - (xdst.right > This->currentDesc.Width) || (xdst.right < 0) || - (xdst.right < xdst.left) || (xdst.bottom < xdst.top))) - { - WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); - ret = WINEDDERR_INVALIDRECT; - goto release; - } - - /* Now handle negative values in the rectangles. Warning: only supported for now - in the 'simple' cases (ie not in any stretching / rotation cases). - - First, the case where nothing is to be done. - */ - if (((xdst.bottom <= 0) || (xdst.right <= 0) || - (xdst.top >= (int) This->currentDesc.Height) || - (xdst.left >= (int) This->currentDesc.Width)) || - ((Src != NULL) && - ((xsrc.bottom <= 0) || (xsrc.right <= 0) || - (xsrc.top >= (int) Src->currentDesc.Height) || - (xsrc.left >= (int) Src->currentDesc.Width)) )) - { - TRACE("Nothing to be done !\n"); - goto release; - } - /* The easy case : the source-less blits.... */ - if (Src == NULL) + 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 */ @@ -867,44 +996,44 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, full_rect.top = 0; full_rect.right = This->currentDesc.Width; full_rect.bottom = This->currentDesc.Height; - IntersectRect(&temp_rect, &full_rect, &xdst); + IntersectRect(&temp_rect, &full_rect, DestRect); xdst = temp_rect; } - else + else if (DestRect) { /* Only handle clipping on the destination rectangle */ - int clip_horiz = (xdst.left < 0) || (xdst.right > (int) This->currentDesc.Width ); - int clip_vert = (xdst.top < 0) || (xdst.bottom > (int) This->currentDesc.Height); + 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) { /* Now check if this is a special case or not... */ - if ((((xdst.bottom - xdst.top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || - (((xdst.right - xdst.left) != (xsrc.right - xsrc.left)) && clip_horiz) || + 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"); - goto release; + return WINED3D_OK; } if (clip_horiz) { - if (xdst.left < 0) { xsrc.left -= xdst.left; xdst.left = 0; } - if (xdst.right > This->currentDesc.Width) + if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; } + if (DestRect->right > This->currentDesc.Width) { - xsrc.right -= (xdst.right - (int) This->currentDesc.Width); + xsrc.right -= (DestRect->right - (int) This->currentDesc.Width); xdst.right = (int) This->currentDesc.Width; } } if (clip_vert) { - if (xdst.top < 0) + if (DestRect->top < 0) { - xsrc.top -= xdst.top; + xsrc.top -= DestRect->top; xdst.top = 0; } - if (xdst.bottom > This->currentDesc.Height) + if (DestRect->bottom > This->currentDesc.Height) { - xsrc.bottom -= (xdst.bottom - (int) This->currentDesc.Height); + xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height); xdst.bottom = (int) This->currentDesc.Height; } } @@ -917,11 +1046,55 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, (xsrc.left >= (int) Src->currentDesc.Width)) { TRACE("Nothing to be done after clipping !\n"); - goto release; + return WINED3D_OK; } } } + if (Src == This) + { + IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); + dfmt = This->resource.format; + slock = dlock; + sfmt = dfmt; + sEntry = getFormatDescEntry(sfmt, NULL, NULL); + dEntry = sEntry; + } + else + { + dfmt = This->resource.format; + dEntry = getFormatDescEntry(dfmt, NULL, NULL); + if (Src) + { + if(This->resource.format != Src->resource.format) { + Src = surface_convert_format(Src, dfmt); + if(!Src) { + /* The conv function writes a FIXME */ + WARN("Cannot convert source surface format to dest format\n"); + goto release; + } + } + IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY); + sfmt = Src->resource.format; + } + sEntry = getFormatDescEntry(sfmt, NULL, NULL); + if (DestRect) + IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0); + else + IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); + } + + if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX; + + if (sEntry->isFourcc && dEntry->isFourcc) + { + if (!DestRect || Src == This) + { + memcpy(dlock.pBits, slock.pBits, This->resource.size); + goto release; + } + } + bpp = This->bytesPerPixel; srcheight = xsrc.bottom - xsrc.top; srcwidth = xsrc.right - xsrc.left; @@ -931,7 +1104,10 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, assert(width <= dlock.Pitch); - dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); + if (DestRect && Src != This) + dbuf = (BYTE*)dlock.pBits; + else + dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); if (Flags & WINEDDBLT_WAIT) { @@ -1016,7 +1192,7 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, sbuf = sbase; /* check for overlapping surfaces */ - if (SrcSurface != iface || xdst.top < xsrc.top || + if (Src != This || xdst.top < xsrc.top || xdst.right <= xsrc.left || xsrc.right <= xdst.left) { /* no overlap, or dst above src, so copy from top downwards */ @@ -1304,7 +1480,9 @@ error: release: IWineD3DSurface_UnlockRect(iface); - if (SrcSurface && SrcSurface != iface) IWineD3DSurface_UnlockRect(SrcSurface); + if (Src && Src != This) IWineD3DSurface_UnlockRect((IWineD3DSurface *) Src); + /* Release the converted surface if any */ + if (Src && SrcSurface != (IWineD3DSurface *) Src) IWineD3DSurface_Release((IWineD3DSurface *) Src); return ret; } @@ -1427,8 +1605,8 @@ IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, /* Since slock was originally copied from this surface's description, we can just reuse it */ assert(This->resource.allocatedMemory != NULL); - sbuf = (BYTE *)This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp; - dbuf = (BYTE *)This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp; + sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp; + dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp; sEntry = getFormatDescEntry(Src->resource.format, NULL, NULL); dEntry = sEntry; } @@ -1514,8 +1692,8 @@ IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, { BYTE *d, *s; DWORD tmp; - s = (BYTE *) sbuf; - d = (BYTE *) dbuf; + s = sbuf; + d = dbuf; for (y = 0; y < h; y++) { for (x = 0; x < w * 3; x += 3) @@ -1544,13 +1722,28 @@ IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, else { int width = w * bpp; + INT sbufpitch, dbufpitch; + TRACE("NO color key copy\n"); + /* Handle overlapping surfaces */ + if (sbuf < dbuf) + { + sbuf += (h - 1) * slock.Pitch; + dbuf += (h - 1) * dlock.Pitch; + sbufpitch = -slock.Pitch; + dbufpitch = -dlock.Pitch; + } + else + { + sbufpitch = slock.Pitch; + dbufpitch = dlock.Pitch; + } for (y = 0; y < h; y++) { /* This is pretty easy, a line for line memcpy */ - memcpy(dbuf, sbuf, width); - sbuf += slock.Pitch; - dbuf += dlock.Pitch; + memmove(dbuf, sbuf, width); + sbuf += sbufpitch; + dbuf += dbufpitch; } TRACE("Copy done\n"); } diff --git a/reactos/dll/directx/wine/wined3d/surface_gdi.c b/reactos/dll/directx/wine/wined3d/surface_gdi.c index 5f569a1c11b..05a4a54671c 100644 --- a/reactos/dll/directx/wine/wined3d/surface_gdi.c +++ b/reactos/dll/directx/wine/wined3d/surface_gdi.c @@ -34,99 +34,6 @@ /* Use the d3d_surface debug channel to have one channel for all surfaces */ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); -WINE_DECLARE_DEBUG_CHANNEL(fps); - -/***************************************************************************** - * x11_copy_to_screen - * - * Helper function that blts the front buffer contents to the target window - * - * Params: - * This: Surface to copy from - * rc: Rectangle to copy - * - *****************************************************************************/ -static void -x11_copy_to_screen(IWineD3DSurfaceImpl *This, - LPRECT rc) -{ - if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) - { - POINT offset = {0,0}; - HWND hDisplayWnd; - HDC hDisplayDC; - HDC hSurfaceDC = 0; - RECT drawrect; - TRACE("(%p)->(%p): Copying to screen\n", This, rc); - - hSurfaceDC = This->hDC; - - hDisplayWnd = This->resource.wineD3DDevice->ddraw_window; - hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE); - if(rc) - { - TRACE(" copying rect (%d,%d)->(%d,%d), offset (%d,%d)\n", - rc->left, rc->top, rc->right, rc->bottom, offset.x, offset.y); - } - - /* Front buffer coordinates are screen coordinates. Map them to the destination - * window if not fullscreened - */ - if(!This->resource.wineD3DDevice->ddraw_fullscreen) { - ClientToScreen(hDisplayWnd, &offset); - } -#if 0 - /* FIXME: this doesn't work... if users really want to run - * X in 8bpp, then we need to call directly into display.drv - * (or Wine's equivalent), and force a private colormap - * without default entries. */ - if (This->palette) { - SelectPalette(hDisplayDC, This->palette->hpal, FALSE); - RealizePalette(hDisplayDC); /* sends messages => deadlocks */ - } -#endif - drawrect.left = 0; - drawrect.right = This->currentDesc.Width; - drawrect.top = 0; - drawrect.bottom = This->currentDesc.Height; - -#if 0 - /* TODO: Support clippers */ - if (This->clipper) - { - RECT xrc; - HWND hwnd = ((IWineD3DClipperImpl *) This->clipper)->hWnd; - if (hwnd && GetClientRect(hwnd,&xrc)) - { - OffsetRect(&xrc,offset.x,offset.y); - IntersectRect(&drawrect,&drawrect,&xrc); - } - } -#endif - if (rc) - { - IntersectRect(&drawrect,&drawrect,rc); - } - else - { - /* Only use this if the caller did not pass a rectangle, since - * due to double locking this could be the wrong one ... - */ - if (This->lockedRect.left != This->lockedRect.right) - { - IntersectRect(&drawrect,&drawrect,&This->lockedRect); - } - } - - BitBlt(hDisplayDC, - drawrect.left-offset.x, drawrect.top-offset.y, - drawrect.right-drawrect.left, drawrect.bottom-drawrect.top, - hSurfaceDC, - drawrect.left, drawrect.top, - SRCCOPY); - ReleaseDC(hDisplayWnd, hDisplayDC); - } -} /***************************************************************************** * IWineD3DSurface::Release, GDI version @@ -140,7 +47,6 @@ ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) { ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); if (ref == 0) { - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice; TRACE("(%p) : cleaning up\n", This); if(This->Flags & SFLAG_DIBSECTION) { @@ -157,8 +63,10 @@ ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) { HeapFree(GetProcessHeap(), 0, This->palette9); IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface); - if(iface == device->ddraw_primary) - device->ddraw_primary = NULL; + + if(This->overlay_dest) { + list_remove(&This->overlay_entry); + } TRACE("(%p) Released\n", This); HeapFree(GetProcessHeap(), 0, This); @@ -182,6 +90,20 @@ IWineGDISurfaceImpl_PreLoad(IWineD3DSurface *iface) ERR("(%p): Please report to wine-devel\n", iface); } +/***************************************************************************** + * IWineD3DSurface::UnLoad, GDI version + * + * This call is unsupported on GDI surfaces, if it's called something went + * wrong in the parent library. Write an informative warning. + * + *****************************************************************************/ +static void WINAPI IWineGDISurfaceImpl_UnLoad(IWineD3DSurface *iface) +{ + ERR("(%p): UnLoad is not supported on X11 surfaces!\n", iface); + ERR("(%p): Most likely the parent library did something wrong.\n", iface); + ERR("(%p): Please report to wine-devel\n", iface); +} + /***************************************************************************** * IWineD3DSurface::LockRect, GDI version * @@ -240,7 +162,7 @@ static HRESULT WINAPI IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DDeviceImpl *dev = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice; + IWineD3DSwapChainImpl *swapchain = NULL; TRACE("(%p)\n", This); if (!(This->Flags & SFLAG_LOCKED)) @@ -269,10 +191,11 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface) } #endif - /* Update the screen */ - if(This == (IWineD3DSurfaceImpl *) dev->ddraw_primary) - { - x11_copy_to_screen(This, &This->lockedRect); + /* Tell the swapchain to update the screen */ + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain); + if(swapchain) { + x11_copy_to_screen(swapchain, &This->lockedRect); + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } This->Flags &= ~SFLAG_LOCKED; @@ -299,101 +222,18 @@ IWineGDISurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - IWineD3DSurfaceImpl *Target = (IWineD3DSurfaceImpl *) override; - TRACE("(%p)->(%p,%x)\n", This, override, Flags); + IWineD3DSwapChainImpl *swapchain = NULL; + HRESULT hr; - TRACE("(%p) Flipping to surface %p\n", This, Target); - - if(Target == NULL) - { - ERR("(%p): Can't flip without a target\n", This); - return WINED3DERR_INVALIDCALL; + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain); + if(!swapchain) { + ERR("Flipped surface is not on a swapchain\n"); + return WINEDDERR_NOTFLIPPABLE; } - /* Flip the DC */ - { - HDC tmp; - tmp = This->hDC; - This->hDC = Target->hDC; - Target->hDC = tmp; - } - - /* Flip the DIBsection */ - { - HBITMAP tmp; - tmp = This->dib.DIBsection; - This->dib.DIBsection = Target->dib.DIBsection; - Target->dib.DIBsection = tmp; - } - - /* Flip the surface data */ - { - void* tmp; - - tmp = This->dib.bitmap_data; - This->dib.bitmap_data = Target->dib.bitmap_data; - Target->dib.bitmap_data = tmp; - - tmp = This->resource.allocatedMemory; - This->resource.allocatedMemory = Target->resource.allocatedMemory; - Target->resource.allocatedMemory = tmp; - - if(This->resource.heapMemory) { - ERR("GDI Surface %p has heap memory allocated\n", This); - } - if(Target->resource.heapMemory) { - ERR("GDI Surface %p has heap memory allocated\n", Target); - } - } - - /* client_memory should not be different, but just in case */ - { - BOOL tmp; - tmp = This->dib.client_memory; - This->dib.client_memory = Target->dib.client_memory; - Target->dib.client_memory = tmp; - } - - /* Useful for debugging */ -#if 0 - { - static unsigned int gen = 0; - char buffer[4096]; - ++gen; - if ((gen % 10) == 0) { - snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen); - IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer); - } - /* - * debugging crash code - if (gen == 250) { - void** test = NULL; - *test = 0; - } - */ - } -#endif - - /* Update the screen */ - x11_copy_to_screen(This, NULL); - - /* FPS support */ - if (TRACE_ON(fps)) - { - static long prev_time, frames; - - DWORD time = GetTickCount(); - frames++; - /* every 1.5 seconds */ - if (time - prev_time > 1500) { - TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time)); - prev_time = time; - frames = 0; - } - } - - return WINED3D_OK; + hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0); + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + return hr; } /***************************************************************************** @@ -478,7 +318,7 @@ const char* filename) table[i][2] = This->palette->palents[i].peBlue; } for (y = 0; y < This->pow2Height; y++) { - unsigned char *src = (unsigned char *) This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface)); + unsigned char *src = This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface)); for (x = 0; x < This->pow2Width; x++) { unsigned char color = *src; src += 1; @@ -490,16 +330,17 @@ const char* filename) fwrite(output, 3 * This->pow2Width, 1, f); } } else { - int red_shift, green_shift, blue_shift, pix_width; + int red_shift, green_shift, blue_shift, pix_width, alpha_shift; pix_width = This->bytesPerPixel; red_shift = get_shift(formatEntry->redMask); green_shift = get_shift(formatEntry->greenMask); blue_shift = get_shift(formatEntry->blueMask); + alpha_shift = get_shift(formatEntry->alphaMask); for (y = 0; y < This->pow2Height; y++) { - unsigned char *src = (unsigned char *) This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface)); + unsigned char *src = This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface)); for (x = 0; x < This->pow2Width; x++) { unsigned int color; unsigned int comp; @@ -515,8 +356,8 @@ const char* filename) output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift; comp = color & formatEntry->greenMask; output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift; - comp = color & formatEntry->blueMask; - output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift; + comp = color & formatEntry->alphaMask; + output[3 * x + 2] = alpha_shift > 0 ? comp >> alpha_shift : comp << -alpha_shift; } fwrite(output, 3 * This->pow2Width, 1, f); } @@ -564,28 +405,28 @@ HRESULT WINAPI IWineGDISurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) { if(This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { unsigned int n; + PALETTEENTRY *pal = NULL; + if(This->palette) { - PALETTEENTRY ent[256]; - - GetPaletteEntries(This->palette->hpal, 0, 256, ent); - for (n=0; n<256; n++) { - col[n].rgbRed = ent[n].peRed; - col[n].rgbGreen = ent[n].peGreen; - col[n].rgbBlue = ent[n].peBlue; - col[n].rgbReserved = 0; - } + pal = This->palette->palents; } else { - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + IWineD3DSurfaceImpl *dds_primary; + IWineD3DSwapChainImpl *swapchain; + swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0]; + dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer; + if (dds_primary && dds_primary->palette) + pal = dds_primary->palette->palents; + } + if (pal) { for (n=0; n<256; n++) { - col[n].rgbRed = device->palettes[device->currentPalette][n].peRed; - col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen; - col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue; + col[n].rgbRed = pal[n].peRed; + col[n].rgbGreen = pal[n].peGreen; + col[n].rgbBlue = pal[n].peBlue; col[n].rgbReserved = 0; } - + SetDIBColorTable(This->hDC, 0, 256, col); } - SetDIBColorTable(This->hDC, 0, 256, col); } *pHDC = This->hDC; @@ -616,6 +457,39 @@ HRESULT WINAPI IWineGDISurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) { return WINED3D_OK; } +HRESULT WINAPI IWineGDISurfaceImpl_RealizePalette(IWineD3DSurface *iface) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + RGBQUAD col[256]; + IWineD3DPaletteImpl *pal = This->palette; + unsigned int n; + IWineD3DSwapChainImpl *swapchain; + TRACE("(%p)\n", This); + + if (!pal) return WINED3D_OK; + + if(This->Flags & SFLAG_DIBSECTION) { + TRACE("(%p): Updating the hdc's palette\n", This); + for (n=0; n<256; n++) { + col[n].rgbRed = pal->palents[n].peRed; + col[n].rgbGreen = pal->palents[n].peGreen; + col[n].rgbBlue = pal->palents[n].peBlue; + col[n].rgbReserved = 0; + } + SetDIBColorTable(This->hDC, 0, 256, col); + } + + /* Update the image because of the palette change. Some games like e.g Red Alert + call SetEntries a lot to implement fading. */ + /* Tell the swapchain to update the screen */ + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain); + if(swapchain) { + x11_copy_to_screen(swapchain, NULL); + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + } + + return WINED3D_OK; +} + /***************************************************************************** * IWineD3DSurface::PrivateSetup, GDI version * @@ -728,7 +602,7 @@ HRESULT WINAPI IWineGDISurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) { /* Now free the old memory if any */ HeapFree(GetProcessHeap(), 0, release); } else if(This->Flags & SFLAG_USERPTR) { - /* Lockrect and GetDC will re-create the dib section and allocated memory */ + /* LockRect and GetDC will re-create the dib section and allocated memory */ This->resource.allocatedMemory = NULL; This->Flags &= ~SFLAG_USERPTR; } @@ -757,6 +631,15 @@ static HRESULT WINAPI IWineGDISurfaceImpl_LoadLocation(IWineD3DSurface *iface, D return WINED3D_OK; } +static WINED3DSURFTYPE WINAPI IWineGDISurfaceImpl_GetImplType(IWineD3DSurface *iface) { + return SURFACE_GDI; +} + +static HRESULT WINAPI IWineGDISurfaceImpl_DrawOverlay(IWineD3DSurface *iface) { + FIXME("GDI surfaces can't draw overlays yet\n"); + return E_FAIL; +} + /* FIXME: This vtable should not use any IWineD3DSurface* implementation functions, * only IWineD3DBaseSurface and IWineGDISurface ones. */ @@ -775,6 +658,7 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DBaseSurfaceImpl_SetPriority, IWineD3DBaseSurfaceImpl_GetPriority, IWineGDISurfaceImpl_PreLoad, + IWineGDISurfaceImpl_UnLoad, IWineD3DBaseSurfaceImpl_GetType, /* IWineD3DSurface */ IWineD3DBaseSurfaceImpl_GetContainer, @@ -792,7 +676,7 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DBaseSurfaceImpl_BltFast, IWineD3DBaseSurfaceImpl_GetPalette, IWineD3DBaseSurfaceImpl_SetPalette, - IWineD3DBaseSurfaceImpl_RealizePalette, + IWineGDISurfaceImpl_RealizePalette, IWineD3DBaseSurfaceImpl_SetColorKey, IWineD3DBaseSurfaceImpl_GetPitch, IWineGDISurfaceImpl_SetMem, @@ -814,5 +698,7 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DBaseSurfaceImpl_SetFormat, IWineGDISurfaceImpl_PrivateSetup, IWineGDISurfaceImpl_ModifyLocation, - IWineGDISurfaceImpl_LoadLocation + IWineGDISurfaceImpl_LoadLocation, + IWineGDISurfaceImpl_GetImplType, + IWineGDISurfaceImpl_DrawOverlay }; diff --git a/reactos/dll/directx/wine/wined3d/swapchain.c b/reactos/dll/directx/wine/wined3d/swapchain.c index 2eaa81258ef..1a82ab8a241 100644 --- a/reactos/dll/directx/wine/wined3d/swapchain.c +++ b/reactos/dll/directx/wine/wined3d/swapchain.c @@ -4,6 +4,7 @@ *Copyright 2002-2003 Jason Edmeades *Copyright 2002-2003 Raphael Junqueira *Copyright 2005 Oliver Stieber + *Copyright 2007-2008 Stefan Dösinger for CodeWeavers * *This library is free software; you can redistribute it and/or *modify it under the terms of the GNU Lesser General Public @@ -34,59 +35,16 @@ WINE_DECLARE_DEBUG_CHANNEL(fps); #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info -/* IDirect3DSwapChain IUnknown parts follow: */ -static ULONG WINAPI IWineD3DSwapChainImpl_AddRef(IWineD3DSwapChain *iface) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - DWORD refCount = InterlockedIncrement(&This->ref); - TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1); - return refCount; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj) -{ - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj); - if (IsEqualGUID(riid, &IID_IUnknown) - || IsEqualGUID(riid, &IID_IWineD3DBase) - || IsEqualGUID(riid, &IID_IWineD3DSwapChain)){ - IWineD3DSwapChainImpl_AddRef(iface); - if(ppobj == NULL){ - ERR("Query interface called but now data allocated\n"); - return E_NOINTERFACE; - } - *ppobj = This; - return WINED3D_OK; - } - *ppobj = NULL; - return E_NOINTERFACE; -} - - -static ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - DWORD refCount; - refCount = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %d\n", This, refCount); - if (refCount == 0) { - IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface); - } - return refCount; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){ - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - *ppParent = This->parent; - IUnknown_AddRef(*ppParent); - TRACE("(%p) returning %p\n", This , *ppParent); - return WINED3D_OK; -} - /*IWineD3DSwapChain parts follow: */ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderTarget) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; WINED3DDISPLAYMODE mode; int i; + TRACE("Destroying swapchain %p\n", 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); @@ -182,40 +140,11 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect); /* TODO: If only source rect or dest rect are supplied then clip the window to match */ - TRACE("preseting HDC %p\n", This->context[0]->hdc); + TRACE("presetting HDC %p\n", This->context[0]->hdc); /* Don't call checkGLcall, as glGetError is not applicable here */ if (hDestWindowOverride && This->win_handle != hDestWindowOverride) { - WINED3DLOCKED_RECT r; - BYTE *mem; - - TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, hDestWindowOverride); - if(This->context[0] == This->wineD3DDevice->contexts[0]) { - /* The primary context 'owns' all the opengl resources. Destroying and recreating that context would require downloading - * all opengl resources, deleting the gl resources, destroying all other contexts, then recreating all other contexts - * and reload the resources - */ - ERR("Cannot change the destination window of the owner of the primary context\n"); - } else { - This->win_handle = hDestWindowOverride; - - /* 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]); - - DestroyContext(This->wineD3DDevice, This->context[0]); - This->context[0] = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer, This->win_handle, FALSE /* pbuffer */, &This->presentParms); - - 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]); - } + IWineD3DSwapChain_SetDestWindowOverride(iface, hDestWindowOverride); } SwapBuffers(This->context[0]->hdc); /* TODO: cycle through the swapchain buffers */ @@ -274,8 +203,24 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO } #endif - if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) { - TRACE("Clearing the color buffer with pink color\n"); + /* This is disabled, but the code left in for debug purposes. + * + * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip, + * we can clear it with some ugly color to make bad drawing visible and ease debugging. + * The Debug runtime does the same on Windows. However, a few games do not redraw the + * screen properly, like Max Payne 2, which leaves a few pixels undefined. + * + * Tests show that the content of the back buffer after a discard flip is indeed not + * reliable, so no game can depend on the exact content. However, it resembles the + * old contents in some way, for example by showing fragments at other locations. In + * general, the color theme is still intact. So Max payne, which draws rather dark scenes + * gets a dark background image. If we clear it with a bright ugly color, the game's + * bug shows up much more than it does on Windows, and the players see single pixels + * with wrong colors. + * (The Max Payne bug has been confirmed on Windows with the debug runtime) + */ + if (FALSE && This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) { + TRACE("Clearing the color buffer with cyan color\n"); IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_TARGET, 0xff00ffff, 1.0, 0); @@ -286,83 +231,32 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */ IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; - BOOL frontuptodate = front->Flags & SFLAG_INSYSMEM; - BOOL backuptodate = back->Flags & SFLAG_INSYSMEM; if(front->resource.size == back->resource.size) { - /* Flip the DC */ - { - HDC tmp; - tmp = front->hDC; - front->hDC = back->hDC; - back->hDC = tmp; - } + DWORD fbflags; + flip_surface(front, back); - /* Flip the DIBsection */ - { - HBITMAP tmp; - BOOL hasDib = front->Flags & SFLAG_DIBSECTION; - tmp = front->dib.DIBsection; - front->dib.DIBsection = back->dib.DIBsection; - back->dib.DIBsection = tmp; - - if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION; - else front->Flags &= ~SFLAG_DIBSECTION; - if(hasDib) back->Flags |= SFLAG_DIBSECTION; - else back->Flags &= ~SFLAG_DIBSECTION; - } - - /* Flip the surface data */ - { - void* tmp; - - tmp = front->dib.bitmap_data; - front->dib.bitmap_data = back->dib.bitmap_data; - back->dib.bitmap_data = tmp; - - tmp = front->resource.allocatedMemory; - front->resource.allocatedMemory = back->resource.allocatedMemory; - back->resource.allocatedMemory = tmp; - - tmp = front->resource.heapMemory; - front->resource.heapMemory = back->resource.heapMemory; - back->resource.heapMemory = tmp; - } - - /* Flip the PBO */ - { - DWORD tmp_flags = front->Flags; - - GLuint tmp_pbo = front->pbo; - front->pbo = back->pbo; - back->pbo = tmp_pbo; - - if(back->Flags & SFLAG_PBO) - front->Flags |= SFLAG_PBO; - else - front->Flags &= ~SFLAG_PBO; - - if(tmp_flags & SFLAG_PBO) - back->Flags |= SFLAG_PBO; - else - back->Flags &= ~SFLAG_PBO; - } - - /* client_memory should not be different, but just in case */ - { - BOOL tmp; - tmp = front->dib.client_memory; - front->dib.client_memory = back->dib.client_memory; - back->dib.client_memory = tmp; - } - if(frontuptodate) back->Flags |= SFLAG_INSYSMEM; - else back->Flags &= ~SFLAG_INSYSMEM; - if(backuptodate) front->Flags |= SFLAG_INSYSMEM; - else front->Flags &= ~SFLAG_INSYSMEM; + /* Tell the front buffer surface that is has been modified. However, + * the other locations were preserved during that, so keep the flags. + * This serves to update the emulated overlay, if any + */ + fbflags = front->Flags; + IWineD3DSurface_ModifyLocation(This->frontBuffer, 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); + /* 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.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && GL_SUPPORT(SGI_VIDEO_SYNC)) { @@ -410,150 +304,64 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO return WINED3D_OK; } -static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) { +static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - POINT start; + WINED3DLOCKED_RECT r; + BYTE *mem; - TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface); + if(window == This->win_handle) return WINED3D_OK; - start.x = 0; - start.y = 0; - - if (This->presentParms.Windowed) { - MapWindowPoints(This->win_handle, NULL, &start, 1); - } - - IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0); - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) { - - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - - if (iBackBuffer > This->presentParms.BackBufferCount - 1) { - TRACE("Back buffer count out of range\n"); - /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here - * in wined3d to avoid problems in other libs + TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, window); + if(This->context[0] == This->wineD3DDevice->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 */ - *ppBackBuffer = NULL; - return WINED3DERR_INVALIDCALL; - } + delete_opengl_contexts((IWineD3DDevice *) This->wineD3DDevice, iface); + This->win_handle = window; + create_primary_opengl_context((IWineD3DDevice *) This->wineD3DDevice, iface); + } else { + This->win_handle = window; - *ppBackBuffer = This->backBuffer[iBackBuffer]; - TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer); + /* 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]); - /* Note inc ref on returned surface */ - if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer); - return WINED3D_OK; + DestroyContext(This->wineD3DDevice, This->context[0]); + This->context[0] = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer, This->win_handle, FALSE /* pbuffer */, &This->presentParms); -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - static BOOL showFixmes = TRUE; - pRasterStatus->InVBlank = TRUE; - pRasterStatus->ScanLine = 0; - /* No openGL equivalent */ - if(showFixmes) { - FIXME("(%p) : stub (once)\n", This); - showFixmes = FALSE; + 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; } -static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - HDC hdc; - int bpp = 0; - - pMode->Width = GetSystemMetrics(SM_CXSCREEN); - pMode->Height = GetSystemMetrics(SM_CYSCREEN); - pMode->RefreshRate = 85; /* FIXME: How to identify? */ - - hdc = GetDC(0); - bpp = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(0, hdc); - - switch (bpp) { - case 8: pMode->Format = WINED3DFMT_R8G8B8; break; - case 16: pMode->Format = WINED3DFMT_R5G6B5; break; - case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */ - case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break; - default: - FIXME("Unrecognized display mode format\n"); - pMode->Format = WINED3DFMT_UNKNOWN; - } - - TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, - pMode->Format, debug_d3dformat(pMode->Format)); - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - - *ppDevice = (IWineD3DDevice *) This->wineD3DDevice; - - /* Note Calling this method will increase the internal reference count - on the IDirect3DDevice9 interface. */ - IWineD3DDevice_AddRef(*ppDevice); - TRACE("(%p) : returning %p\n", This, *ppDevice); - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - TRACE("(%p)\n", This); - - *pPresentationParameters = This->presentParms; - - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){ - - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - HDC hDC; - TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags); - hDC = GetDC(This->win_handle); - SetDeviceGammaRamp(hDC, (LPVOID)pRamp); - ReleaseDC(This->win_handle, hDC); - return WINED3D_OK; - -} - -static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){ - - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - HDC hDC; - TRACE("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); - GetDeviceGammaRamp(hDC, pRamp); - ReleaseDC(This->win_handle, hDC); - return WINED3D_OK; - -} - - const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl = { /* IUnknown */ - IWineD3DSwapChainImpl_QueryInterface, - IWineD3DSwapChainImpl_AddRef, - IWineD3DSwapChainImpl_Release, + IWineD3DBaseSwapChainImpl_QueryInterface, + IWineD3DBaseSwapChainImpl_AddRef, + IWineD3DBaseSwapChainImpl_Release, /* IWineD3DSwapChain */ - IWineD3DSwapChainImpl_GetParent, + IWineD3DBaseSwapChainImpl_GetParent, IWineD3DSwapChainImpl_Destroy, - IWineD3DSwapChainImpl_GetDevice, + IWineD3DBaseSwapChainImpl_GetDevice, IWineD3DSwapChainImpl_Present, - IWineD3DSwapChainImpl_GetFrontBufferData, - IWineD3DSwapChainImpl_GetBackBuffer, - IWineD3DSwapChainImpl_GetRasterStatus, - IWineD3DSwapChainImpl_GetDisplayMode, - IWineD3DSwapChainImpl_GetPresentParameters, - IWineD3DSwapChainImpl_SetGammaRamp, - IWineD3DSwapChainImpl_GetGammaRamp + IWineD3DSwapChainImpl_SetDestWindowOverride, + IWineD3DBaseSwapChainImpl_GetFrontBufferData, + IWineD3DBaseSwapChainImpl_GetBackBuffer, + IWineD3DBaseSwapChainImpl_GetRasterStatus, + IWineD3DBaseSwapChainImpl_GetDisplayMode, + IWineD3DBaseSwapChainImpl_GetPresentParameters, + IWineD3DBaseSwapChainImpl_SetGammaRamp, + IWineD3DBaseSwapChainImpl_GetGammaRamp }; WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) { @@ -585,3 +393,11 @@ WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain * TRACE("Returning context %p\n", ctx); return ctx; } + +void get_drawable_size_swapchain(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { + /* The drawable size of an onscreen drawable is the surface size. + * (Actually: The window size, but the surface is created in window size) + */ + *width = This->currentDesc.Width; + *height = This->currentDesc.Height; +} diff --git a/reactos/dll/directx/wine/wined3d/swapchain_base.c b/reactos/dll/directx/wine/wined3d/swapchain_base.c new file mode 100644 index 00000000000..75adf7720e1 --- /dev/null +++ b/reactos/dll/directx/wine/wined3d/swapchain_base.c @@ -0,0 +1,191 @@ +/* + *IDirect3DSwapChain9 implementation + * + *Copyright 2002-2003 Jason Edmeades + *Copyright 2002-2003 Raphael Junqueira + *Copyright 2005 Oliver Stieber + *Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * + *This library is free software; you can redistribute it and/or + *modify it under the terms of the GNU Lesser General Public + *License as published by the Free Software Foundation; either + *version 2.1 of the License, or (at your option) any later version. + * + *This library is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + *Lesser General Public License for more details. + * + *You should have received a copy of the GNU Lesser General Public + *License along with this library; if not, write to the Free Software + *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); + +/* IDirect3DSwapChain IUnknown parts follow: */ +HRESULT WINAPI IWineD3DBaseSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj) +{ + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj); + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IWineD3DBase) + || IsEqualGUID(riid, &IID_IWineD3DSwapChain)){ + IWineD3DSwapChain_AddRef(iface); + if(ppobj == NULL){ + ERR("Query interface called but now data allocated\n"); + return E_NOINTERFACE; + } + *ppobj = This; + return WINED3D_OK; + } + *ppobj = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI IWineD3DBaseSwapChainImpl_AddRef(IWineD3DSwapChain *iface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + DWORD refCount = InterlockedIncrement(&This->ref); + TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1); + return refCount; +} + +ULONG WINAPI IWineD3DBaseSwapChainImpl_Release(IWineD3DSwapChain *iface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + DWORD refCount; + refCount = InterlockedDecrement(&This->ref); + TRACE("(%p) : ReleaseRef to %d\n", This, refCount); + if (refCount == 0) { + IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface); + } + return refCount; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){ + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + *ppParent = This->parent; + IUnknown_AddRef(*ppParent); + TRACE("(%p) returning %p\n", This , *ppParent); + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + POINT start; + + TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface); + + start.x = 0; + start.y = 0; + + if (This->presentParms.Windowed) { + MapWindowPoints(This->win_handle, NULL, &start, 1); + } + + IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0); + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) { + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + if (iBackBuffer > This->presentParms.BackBufferCount - 1) { + TRACE("Back buffer count out of range\n"); + /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here + * in wined3d to avoid problems in other libs + */ + *ppBackBuffer = NULL; + return WINED3DERR_INVALIDCALL; + } + + /* Return invalid if there is no backbufferarray, otherwise it will crash when ddraw is + * used (there This->backBuffer is allways NULL). We need this because this function have + * to be called from IWineD3DStateBlockImpl_InitStartupStateBlock to get the default + * scissorrect dimensions. */ + if( !This->backBuffer ) { + *ppBackBuffer = NULL; + return WINED3DERR_INVALIDCALL; + } + + *ppBackBuffer = This->backBuffer[iBackBuffer]; + TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer); + + /* Note inc ref on returned surface */ + if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer); + return WINED3D_OK; + +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + static BOOL showFixmes = TRUE; + pRasterStatus->InVBlank = TRUE; + pRasterStatus->ScanLine = 0; + /* No openGL equivalent */ + if(showFixmes) { + FIXME("(%p) : stub (once)\n", This); + showFixmes = FALSE; + } + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HRESULT hr; + + TRACE("(%p)->(%p): Calling GetAdapterDisplayMode\n", This, pMode); + hr = IWineD3D_GetAdapterDisplayMode(This->wineD3DDevice->wineD3D, This->wineD3DDevice->adapter->num, pMode); + + TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, + pMode->Format, debug_d3dformat(pMode->Format)); + return hr; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + *ppDevice = (IWineD3DDevice *) This->wineD3DDevice; + + /* Note Calling this method will increase the internal reference count + on the IDirect3DDevice9 interface. */ + IWineD3DDevice_AddRef(*ppDevice); + TRACE("(%p) : returning %p\n", This, *ppDevice); + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + TRACE("(%p)\n", This); + + *pPresentationParameters = This->presentParms; + + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){ + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HDC hDC; + TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags); + hDC = GetDC(This->win_handle); + SetDeviceGammaRamp(hDC, (LPVOID)pRamp); + ReleaseDC(This->win_handle, hDC); + return WINED3D_OK; + +} + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){ + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HDC hDC; + TRACE("(%p) : pRamp@%p\n", This, pRamp); + hDC = GetDC(This->win_handle); + GetDeviceGammaRamp(hDC, pRamp); + ReleaseDC(This->win_handle, hDC); + return WINED3D_OK; + +} diff --git a/reactos/dll/directx/wine/wined3d/swapchain_gdi.c b/reactos/dll/directx/wine/wined3d/swapchain_gdi.c new file mode 100644 index 00000000000..d76b9b5e3fa --- /dev/null +++ b/reactos/dll/directx/wine/wined3d/swapchain_gdi.c @@ -0,0 +1,272 @@ +/* + *IDirect3DSwapChain9 implementation + * + *Copyright 2002-2003 Jason Edmeades + *Copyright 2002-2003 Raphael Junqueira + *Copyright 2005 Oliver Stieber + *Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * + *This library is free software; you can redistribute it and/or + *modify it under the terms of the GNU Lesser General Public + *License as published by the Free Software Foundation; either + *version 2.1 of the License, or (at your option) any later version. + * + *This library is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + *Lesser General Public License for more details. + * + *You should have received a copy of the GNU Lesser General Public + *License along with this library; if not, write to the Free Software + *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(fps); + +static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderback) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + WINED3DDISPLAYMODE mode; + + TRACE("Destroying swapchain %p\n", 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(D3DCB_DestroyRenderback(This->frontBuffer) > 0) { + FIXME("(%p) Something's still holding the front buffer\n",This); + } + } + + if(This->backBuffer) { + int i; + for(i = 0; i < This->presentParms.BackBufferCount; i++) { + IWineD3DSurface_SetContainer(This->backBuffer[i], 0); + if(D3DCB_DestroyRenderback(This->backBuffer[i]) > 0) { + FIXME("(%p) Something's still holding the back buffer\n",This); + } + } + HeapFree(GetProcessHeap(), 0, This->backBuffer); + } + + /* Restore the screen resolution if we rendered in fullscreen + * This will restore the screen resolution to what it was before creating the swapchain. In case of d3d8 and d3d9 + * this will be the original desktop resolution. In case of d3d7 this will be a NOP because ddraw sets the resolution + * before starting up Direct3D, thus orig_width and orig_height will be equal to the modes in the presentation params + */ + if(This->presentParms.Windowed == FALSE) { + mode.Width = This->orig_width; + mode.Height = This->orig_height; + mode.RefreshRate = 0; + mode.Format = This->orig_fmt; + IWineD3DDevice_SetDisplayMode((IWineD3DDevice *) This->wineD3DDevice, 0, &mode); + } + + HeapFree(GetProcessHeap(), 0, This); +} + +/***************************************************************************** + * x11_copy_to_screen + * + * Helper function that blts the front buffer contents to the target window + * + * Params: + * This: Surface to copy from + * rc: Rectangle to copy + * + *****************************************************************************/ +void x11_copy_to_screen(IWineD3DSwapChainImpl *This, LPRECT rc) { + IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; + + if(front->resource.usage & WINED3DUSAGE_RENDERTARGET) { + POINT offset = {0,0}; + HWND hDisplayWnd; + HDC hDisplayDC; + HDC hSurfaceDC = 0; + RECT drawrect; + TRACE("(%p)->(%p): Copying to screen\n", front, rc); + + hSurfaceDC = front->hDC; + + hDisplayWnd = This->win_handle; + hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE); + if(rc) { + TRACE(" copying rect (%d,%d)->(%d,%d), offset (%d,%d)\n", + rc->left, rc->top, rc->right, rc->bottom, offset.x, offset.y); + } + + /* Front buffer coordinates are screen coordinates. Map them to the destination + * window if not fullscreened + */ + if(This->presentParms.Windowed) { + ClientToScreen(hDisplayWnd, &offset); + } +#if 0 + /* FIXME: This doesn't work... if users really want to run + * X in 8bpp, then we need to call directly into display.drv + * (or Wine's equivalent), and force a private colormap + * without default entries. */ + if (front->palette) { + SelectPalette(hDisplayDC, front->palette->hpal, FALSE); + RealizePalette(hDisplayDC); /* sends messages => deadlocks */ + } +#endif + drawrect.left = 0; + drawrect.right = front->currentDesc.Width; + drawrect.top = 0; + drawrect.bottom = front->currentDesc.Height; + +#if 0 + /* TODO: Support clippers */ + if (front->clipper) + { + RECT xrc; + HWND hwnd = ((IWineD3DClipperImpl *) front->clipper)->hWnd; + if (hwnd && GetClientRect(hwnd,&xrc)) + { + OffsetRect(&xrc,offset.x,offset.y); + IntersectRect(&drawrect,&drawrect,&xrc); + } + } +#endif + if (rc) { + IntersectRect(&drawrect,&drawrect,rc); + } + else { + /* Only use this if the caller did not pass a rectangle, since + * due to double locking this could be the wrong one ... + */ + if (front->lockedRect.left != front->lockedRect.right) { + IntersectRect(&drawrect,&drawrect,&front->lockedRect); + } + } + + BitBlt(hDisplayDC, + drawrect.left-offset.x, drawrect.top-offset.y, + drawrect.right-drawrect.left, drawrect.bottom-drawrect.top, + hSurfaceDC, + drawrect.left, drawrect.top, + SRCCOPY); + ReleaseDC(hDisplayWnd, hDisplayDC); + } +} + +static HRESULT WINAPI IWineGDISwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + This->win_handle = window; + return WINED3D_OK; +} + +static HRESULT WINAPI IWineGDISwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface; + IWineD3DSurfaceImpl *front, *back; + + if(!This->backBuffer) { + WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + front = (IWineD3DSurfaceImpl *) This->frontBuffer; + back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; + + /* Flip the DC */ + { + HDC tmp; + tmp = front->hDC; + front->hDC = back->hDC; + back->hDC = tmp; + } + + /* Flip the DIBsection */ + { + HBITMAP tmp; + tmp = front->dib.DIBsection; + front->dib.DIBsection = back->dib.DIBsection; + back->dib.DIBsection = tmp; + } + + /* Flip the surface data */ + { + void* tmp; + + tmp = front->dib.bitmap_data; + front->dib.bitmap_data = back->dib.bitmap_data; + back->dib.bitmap_data = tmp; + + tmp = front->resource.allocatedMemory; + front->resource.allocatedMemory = back->resource.allocatedMemory; + back->resource.allocatedMemory = tmp; + + if(front->resource.heapMemory) { + ERR("GDI Surface %p has heap memory allocated\n", front); + } + if(back->resource.heapMemory) { + ERR("GDI Surface %p has heap memory allocated\n", back); + } + } + + /* client_memory should not be different, but just in case */ + { + BOOL tmp; + tmp = front->dib.client_memory; + front->dib.client_memory = back->dib.client_memory; + back->dib.client_memory = tmp; + } + + /* FPS support */ + if (TRACE_ON(fps)) + { + static long prev_time, frames; + + DWORD time = GetTickCount(); + frames++; + /* every 1.5 seconds */ + if (time - prev_time > 1500) { + TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time)); + prev_time = time; + frames = 0; + } + } + + x11_copy_to_screen(This, NULL); + + return WINED3D_OK; +} + +/* FIXME: This should not be needed, the base version is OK */ +HRESULT WINAPI IWineGDIBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + IWineD3DDeviceImpl *device = This->wineD3DDevice; + + pMode->Width = device->ddraw_width; + pMode->Height = device->ddraw_height; + pMode->Format = device->ddraw_format; + pMode->RefreshRate = 0; + return WINED3D_OK; +} + +const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl = +{ + /* IUnknown */ + IWineD3DBaseSwapChainImpl_QueryInterface, + IWineD3DBaseSwapChainImpl_AddRef, + IWineD3DBaseSwapChainImpl_Release, + /* IWineD3DSwapChain */ + IWineD3DBaseSwapChainImpl_GetParent, + IWineGDISwapChainImpl_Destroy, + IWineD3DBaseSwapChainImpl_GetDevice, + IWineGDISwapChainImpl_Present, + IWineGDISwapChainImpl_SetDestWindowOverride, + IWineD3DBaseSwapChainImpl_GetFrontBufferData, + IWineD3DBaseSwapChainImpl_GetBackBuffer, + IWineD3DBaseSwapChainImpl_GetRasterStatus, + IWineD3DBaseSwapChainImpl_GetDisplayMode, + IWineD3DBaseSwapChainImpl_GetPresentParameters, + IWineD3DBaseSwapChainImpl_SetGammaRamp, + IWineD3DBaseSwapChainImpl_GetGammaRamp +}; diff --git a/reactos/dll/directx/wine/wined3d/texture.c b/reactos/dll/directx/wine/wined3d/texture.c index 1bdd6640647..f1384373fa2 100644 --- a/reactos/dll/directx/wine/wined3d/texture.c +++ b/reactos/dll/directx/wine/wined3d/texture.c @@ -4,6 +4,7 @@ * Copyright 2002-2005 Jason Edmeades * Copyright 2002-2005 Raphael Junqueira * Copyright 2005 Oliver Stieber + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -95,7 +96,6 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { /* Override the IWineD3DResource PreLoad method */ unsigned int i; - BOOL setGlTextureDesc = FALSE; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; BOOL srgb_mode = This->baseTexture.is_srgb; @@ -103,8 +103,6 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { TRACE("(%p) : About to load texture\n", This); - if (This->baseTexture.textureName == 0) setGlTextureDesc = TRUE; - if(!device->isInDraw) { /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, thus no danger of * recursive calls @@ -116,13 +114,20 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { This->baseTexture.is_srgb = srgb_mode; } - IWineD3DTexture_BindTexture(iface); - ENTER_GL(); + if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { + for (i = 0; i < This->baseTexture.levels; i++) { + if(palette9_changed((IWineD3DSurfaceImpl *)This->surfaces[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[i], 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); + } + } + } /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */ if (This->baseTexture.dirty) { for (i = 0; i < This->baseTexture.levels; i++) { - if(setGlTextureDesc) - IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], This->baseTexture.textureName, IWineD3DTexture_GetTextureDimensions(iface)); IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); } } else if (srgb_was_toggled) { @@ -139,7 +144,6 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { } else { TRACE("(%p) Texture not dirty, nothing to do\n" , iface); } - LEAVE_GL(); /* No longer dirty */ This->baseTexture.dirty = FALSE; @@ -147,6 +151,23 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { return ; } +static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) { + unsigned int i; + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + TRACE("(%p)\n", This); + + /* 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++) { + IWineD3DSurface_UnLoad(This->surfaces[i]); + IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], 0, IWineD3DTexture_GetTextureDimensions(iface)); + } + + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); +} + static WINED3DRESOURCETYPE WINAPI IWineD3DTextureImpl_GetType(IWineD3DTexture *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -193,21 +214,56 @@ static BOOL WINAPI IWineD3DTextureImpl_GetDirty(IWineD3DTexture *iface) { static HRESULT WINAPI IWineD3DTextureImpl_BindTexture(IWineD3DTexture *iface) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - TRACE("(%p) : relay to BaseTexture\n", This); - return IWineD3DBaseTextureImpl_BindTexture((IWineD3DBaseTexture *)iface); -} + BOOL set_gl_texture_desc = This->baseTexture.textureName == 0; + HRESULT hr; -static HRESULT WINAPI IWineD3DTextureImpl_UnBindTexture(IWineD3DTexture *iface) { - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; TRACE("(%p) : relay to BaseTexture\n", This); - return IWineD3DBaseTextureImpl_UnBindTexture((IWineD3DBaseTexture *)iface); + + hr = IWineD3DBaseTextureImpl_BindTexture((IWineD3DBaseTexture *)iface); + if (set_gl_texture_desc && SUCCEEDED(hr)) { + UINT i; + for (i = 0; i < This->baseTexture.levels; ++i) { + IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], This->baseTexture.textureName, IWineD3DTexture_GetTextureDimensions(iface)); + } + /* 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); + checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)"); + glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)"); + glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_MIN_FILTER, GL_NEAREST); + checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MIN_FILTER, GL_NEAREST)"); + glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_MAG_FILTER, GL_NEAREST); + checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MAG_FILTER, GL_NEAREST)"); + LEAVE_GL(); + This->baseTexture.states[WINED3DTEXSTA_ADDRESSU] = WINED3DTADDRESS_CLAMP; + This->baseTexture.states[WINED3DTEXSTA_ADDRESSV] = WINED3DTADDRESS_CLAMP; + This->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT; + This->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; + This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE; + } + } + + return hr; } static UINT WINAPI IWineD3DTextureImpl_GetTextureDimensions(IWineD3DTexture *iface) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; TRACE("(%p)\n", This); - return GL_TEXTURE_2D; + return This->target; +} + +static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) { + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + TRACE("(%p)\n", This); + + return This->cond_np2; } static void WINAPI IWineD3DTextureImpl_ApplyStateChanges(IWineD3DTexture *iface, @@ -256,7 +312,7 @@ static HRESULT WINAPI IWineD3DTextureImpl_GetSurfaceLevel(IWineD3DTexture *iface if (Level < This->baseTexture.levels) { *ppSurfaceLevel = This->surfaces[Level]; - IWineD3DSurface_AddRef((IWineD3DSurface*) This->surfaces[Level]); + IWineD3DSurface_AddRef(This->surfaces[Level]); hr = WINED3D_OK; TRACE("(%p) : returning %p for level %d\n", This, *ppSurfaceLevel, Level); } @@ -321,6 +377,7 @@ const IWineD3DTextureVtbl IWineD3DTexture_Vtbl = IWineD3DTextureImpl_SetPriority, IWineD3DTextureImpl_GetPriority, IWineD3DTextureImpl_PreLoad, + IWineD3DTextureImpl_UnLoad, IWineD3DTextureImpl_GetType, /* IWineD3DBaseTexture */ IWineD3DTextureImpl_SetLOD, @@ -332,8 +389,8 @@ const IWineD3DTextureVtbl IWineD3DTexture_Vtbl = IWineD3DTextureImpl_SetDirty, IWineD3DTextureImpl_GetDirty, IWineD3DTextureImpl_BindTexture, - IWineD3DTextureImpl_UnBindTexture, IWineD3DTextureImpl_GetTextureDimensions, + IWineD3DTextureImpl_IsCondNP2, IWineD3DTextureImpl_ApplyStateChanges, /* IWineD3DTexture */ IWineD3DTextureImpl_Destroy, diff --git a/reactos/dll/directx/wine/wined3d/utils.c b/reactos/dll/directx/wine/wined3d/utils.c index e108fca3078..57e2b37778a 100644 --- a/reactos/dll/directx/wine/wined3d/utils.c +++ b/reactos/dll/directx/wine/wined3d/utils.c @@ -5,7 +5,8 @@ * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber - * Copyright 2006-2007 Henri Verbeet + * Copyright 2006-2008 Henri Verbeet + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,13 +30,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); /***************************************************************************** * Pixel format array + * + * For the formats WINED3DFMT_A32B32G32R32F, WINED3DFMT_A16B16G16R16F, + * and WINED3DFMT_A16B16G16R16 do not have correct alpha masks, because the + * high masks do not fit into the 32 bit values needed for ddraw. It is only + * used for ddraw mostly, and to figure out if the format has alpha at all, so + * setting a mask like 0x1 for those surfaces is correct. The 64 and 128 bit + * formats are not usable in 2D rendering because ddraw doesn't support them. */ static const StaticPixelFormatDesc formats[] = { /*{WINED3DFORMAT ,alphamask ,redmask ,greenmask ,bluemask ,bpp ,depth ,stencil, isFourcc*/ {WINED3DFMT_UNKNOWN ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,FALSE }, /* FourCC formats, kept here to have WINED3DFMT_R8G8B8(=20) at position 20 */ - {WINED3DFMT_UYVY ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,0 ,0 ,TRUE }, - {WINED3DFMT_YUY2 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,0 ,0 ,TRUE }, + {WINED3DFMT_UYVY ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,TRUE }, + {WINED3DFMT_YUY2 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,TRUE }, + {WINED3DFMT_YV12 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,TRUE }, {WINED3DFMT_DXT1 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,TRUE }, {WINED3DFMT_DXT2 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,TRUE }, {WINED3DFMT_DXT3 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,TRUE }, @@ -47,13 +56,13 @@ static const StaticPixelFormatDesc formats[] = { /* IEEE formats */ {WINED3DFMT_R32F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,0 ,0 ,FALSE }, {WINED3DFMT_G32R32F ,0x0 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE }, - {WINED3DFMT_A32B32G32R32F,0x0 ,0x0 ,0x0 ,0x0 ,16 ,0 ,0 ,FALSE }, + {WINED3DFMT_A32B32G32R32F,0x1 ,0x0 ,0x0 ,0x0 ,16 ,0 ,0 ,FALSE }, /* Hmm? */ {WINED3DFMT_CxV8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE }, /* Float */ {WINED3DFMT_R16F ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE }, {WINED3DFMT_G16R16F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,0 ,0 ,FALSE }, - {WINED3DFMT_A16B16G16R16F,0x0 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE }, + {WINED3DFMT_A16B16G16R16F,0x1 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE }, /* Palettized formats */ {WINED3DFMT_A8P8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE }, {WINED3DFMT_P8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,FALSE }, @@ -74,7 +83,7 @@ static const StaticPixelFormatDesc formats[] = { {WINED3DFMT_X8B8G8R8 ,0x0 ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4 ,0 ,0 ,FALSE }, {WINED3DFMT_G16R16 ,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,4 ,0 ,0 ,FALSE }, {WINED3DFMT_A2R10G10B10 ,0xb0000000 ,0x3ff00000 ,0x000ffc00 ,0x000003ff ,4 ,0 ,0 ,FALSE }, - {WINED3DFMT_A16B16G16R16,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,8 ,0 ,0 ,FALSE }, + {WINED3DFMT_A16B16G16R16,0x1 ,0x0000ffff ,0xffff0000 ,0x0 ,8 ,0 ,0 ,FALSE }, /* Luminance */ {WINED3DFMT_L8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,FALSE }, {WINED3DFMT_A8L8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE }, @@ -103,11 +112,16 @@ static const StaticPixelFormatDesc formats[] = { {WINED3DFMT_INDEX16 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE }, {WINED3DFMT_INDEX32 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,0 ,0 ,FALSE }, {WINED3DFMT_Q16W16V16U16,0x0 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE }, + /* Vendor-specific formats */ + {WINED3DFMT_ATI2N ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,TRUE }, + {WINED3DFMT_NVHU ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,TRUE }, + {WINED3DFMT_NVHS ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,TRUE }, }; typedef struct { WINED3DFORMAT fmt; - GLint glInternal, glGammaInternal, glFormat, glType; + GLint glInternal, glGammaInternal, rtInternal, glFormat, glType; + unsigned int Flags; } GlPixelFormatDescTemplate; /***************************************************************************** @@ -117,78 +131,155 @@ typedef struct { * table. */ static const GlPixelFormatDescTemplate gl_formats_template[] = { - /*{ internal ,srgbInternal ,format ,type }*/ - {WINED3DFMT_UNKNOWN ,0 ,0 ,0 ,0 }, + /*{ internal ,srgbInternal , rtInternal, format ,type \ + ,Flags }*/ + {WINED3DFMT_UNKNOWN ,0 ,0 , 0, 0 ,0 + ,0 }, /* FourCC formats */ - {WINED3DFMT_UYVY ,0 ,0 ,0 ,0 }, - {WINED3DFMT_YUY2 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_DXT1 ,GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_DXT2 ,GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_DXT3 ,GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_DXT4 ,GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_DXT5 ,GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_MULTI2_ARGB8 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_G8R8_G8B8 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_R8G8_B8G8 ,0 ,0 ,0 ,0 }, + /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type + * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The + * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based + * Macs, so probably the endianess differs. This could be tested as soon as we have a Windows and MacOS on a big + * endian machine + */ + {WINED3DFMT_UYVY ,GL_RGB ,GL_RGB , 0, GL_YCBCR_422_APPLE ,UNSIGNED_SHORT_8_8_APPLE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_YUY2 ,GL_RGB ,GL_RGB , 0, GL_YCBCR_422_APPLE ,UNSIGNED_SHORT_8_8_REV_APPLE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_YV12 ,GL_ALPHA ,GL_ALPHA , 0, GL_ALPHA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_DXT1 ,GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT , 0, GL_RGBA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_DXT2 ,GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT , 0, GL_RGBA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_DXT3 ,GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT , 0, GL_RGBA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_DXT4 ,GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT , 0, GL_RGBA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_DXT5 ,GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT , 0, GL_RGBA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_MULTI2_ARGB8 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_G8R8_G8B8 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_R8G8_B8G8 ,0 ,0 , 0, 0 ,0 + ,0 }, /* IEEE formats */ - {WINED3DFMT_R32F ,GL_RGB32F_ARB ,GL_RGB32F_ARB ,GL_RED ,GL_FLOAT }, - {WINED3DFMT_G32R32F ,0 ,0 ,0 ,0 }, - {WINED3DFMT_A32B32G32R32F ,GL_RGBA32F_ARB ,GL_RGBA32F_ARB ,GL_RGBA ,GL_FLOAT }, + {WINED3DFMT_R32F ,GL_RGB32F_ARB ,GL_RGB32F_ARB , 0, GL_RED ,GL_FLOAT + ,WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_G32R32F ,0 ,0 , 0, 0 ,0 + ,WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_A32B32G32R32F ,GL_RGBA32F_ARB ,GL_RGBA32F_ARB , 0, GL_RGBA ,GL_FLOAT + ,WINED3DFMT_FLAG_RENDERTARGET }, /* Hmm? */ - {WINED3DFMT_CxV8U8 ,0 ,0 ,0 ,0 }, + {WINED3DFMT_CxV8U8 ,0 ,0 , 0, 0 ,0 + ,0 }, /* Float */ - {WINED3DFMT_R16F ,GL_RGB16F_ARB ,GL_RGB16F_ARB ,GL_RED ,GL_HALF_FLOAT_ARB }, - {WINED3DFMT_G16R16F ,0 ,0 ,0 ,0 }, - {WINED3DFMT_A16B16G16R16F ,GL_RGBA16F_ARB ,GL_RGBA16F_ARB ,GL_RGBA ,GL_HALF_FLOAT_ARB }, + {WINED3DFMT_R16F ,GL_RGB16F_ARB ,GL_RGB16F_ARB , 0, GL_RED ,GL_HALF_FLOAT_ARB + ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_G16R16F ,0 ,0 , 0, 0 ,0 + ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_A16B16G16R16F ,GL_RGBA16F_ARB ,GL_RGBA16F_ARB , 0, GL_RGBA ,GL_HALF_FLOAT_ARB + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, /* Palettized formats */ - {WINED3DFMT_A8P8, 0 ,0 ,0 ,0 }, - {WINED3DFMT_P8, GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX ,GL_UNSIGNED_BYTE }, + {WINED3DFMT_A8P8, 0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_P8, GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT , 0, GL_COLOR_INDEX ,GL_UNSIGNED_BYTE + ,0 }, /* Standard ARGB formats */ - {WINED3DFMT_R8G8B8 ,GL_RGB8 ,GL_RGB8 ,GL_BGR ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_A8R8G8B8 ,GL_RGBA8 ,GL_SRGB8_ALPHA8_EXT ,GL_BGRA ,GL_UNSIGNED_INT_8_8_8_8_REV }, - {WINED3DFMT_X8R8G8B8 ,GL_RGB8 ,GL_SRGB8_EXT ,GL_BGRA ,GL_UNSIGNED_INT_8_8_8_8_REV }, - {WINED3DFMT_R5G6B5 ,GL_RGB5 ,GL_RGB5 ,GL_RGB ,GL_UNSIGNED_SHORT_5_6_5 }, - {WINED3DFMT_X1R5G5B5 ,GL_RGB5 ,GL_RGB5_A1 ,GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV }, - {WINED3DFMT_A1R5G5B5 ,GL_RGB5_A1 ,GL_RGB5_A1 ,GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV }, - {WINED3DFMT_A4R4G4B4 ,GL_RGBA4 ,GL_SRGB8_ALPHA8_EXT ,GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV }, - {WINED3DFMT_R3G3B2 ,GL_R3_G3_B2 ,GL_R3_G3_B2 ,GL_RGB ,GL_UNSIGNED_BYTE_3_3_2 }, - {WINED3DFMT_A8 ,GL_ALPHA8 ,GL_ALPHA8 ,GL_ALPHA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_A8R3G3B2 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_X4R4G4B4 ,GL_RGB4 ,GL_RGB4 ,GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV }, - {WINED3DFMT_A2B10G10R10 ,GL_RGBA ,GL_RGBA ,GL_RGBA ,GL_UNSIGNED_INT_2_10_10_10_REV }, - {WINED3DFMT_A8B8G8R8 ,GL_RGBA8 ,GL_RGBA8 ,GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV }, - {WINED3DFMT_X8B8G8R8 ,GL_RGB8 ,GL_RGB8 ,GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV }, - {WINED3DFMT_G16R16 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_A2R10G10B10 ,GL_RGBA ,GL_RGBA ,GL_BGRA ,GL_UNSIGNED_INT_2_10_10_10_REV }, - {WINED3DFMT_A16B16G16R16 ,GL_RGBA16_EXT ,GL_RGBA16_EXT ,GL_RGBA ,GL_UNSIGNED_SHORT }, + {WINED3DFMT_R8G8B8 ,GL_RGB8 ,GL_RGB8 , 0, GL_BGR ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_A8R8G8B8 ,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 }, + {WINED3DFMT_X8R8G8B8 ,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 }, + {WINED3DFMT_R5G6B5 ,GL_RGB5 ,GL_RGB5 , GL_RGB8, GL_RGB ,GL_UNSIGNED_SHORT_5_6_5 + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, + {WINED3DFMT_X1R5G5B5 ,GL_RGB5 ,GL_RGB5_A1 , 0, GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A1R5G5B5 ,GL_RGB5_A1 ,GL_RGB5_A1 , 0, GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A4R4G4B4 ,GL_RGBA4 ,GL_SRGB8_ALPHA8_EXT , 0, GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_R3G3B2 ,GL_R3_G3_B2 ,GL_R3_G3_B2 , 0, GL_RGB ,GL_UNSIGNED_BYTE_3_3_2 + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING }, + {WINED3DFMT_A8 ,GL_ALPHA8 ,GL_ALPHA8 , 0, GL_ALPHA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING }, + {WINED3DFMT_A8R3G3B2 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_X4R4G4B4 ,GL_RGB4 ,GL_RGB4 , 0, GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + {WINED3DFMT_A2B10G10R10 ,GL_RGB10_A2 ,GL_RGB10_A2 , 0, GL_RGBA ,GL_UNSIGNED_INT_2_10_10_10_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + {WINED3DFMT_A8B8G8R8 ,GL_RGBA8 ,GL_RGBA8 , 0, GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + {WINED3DFMT_X8B8G8R8 ,GL_RGB8 ,GL_RGB8 , 0, GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + {WINED3DFMT_G16R16 ,GL_RGB16_EXT ,GL_RGB16_EXT , 0, GL_RGB ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A2R10G10B10 ,GL_RGB10_A2 ,GL_RGB10_A2 , 0, GL_BGRA ,GL_UNSIGNED_INT_2_10_10_10_REV + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A16B16G16R16 ,GL_RGBA16_EXT ,GL_RGBA16_EXT , 0, GL_RGBA ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, /* Luminance */ - {WINED3DFMT_L8 ,GL_LUMINANCE8 ,GL_SLUMINANCE8_EXT ,GL_LUMINANCE ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_A8L8 ,GL_LUMINANCE8_ALPHA8 ,GL_SLUMINANCE8_ALPHA8_EXT ,GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE }, - {WINED3DFMT_A4L4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE }, + {WINED3DFMT_L8 ,GL_LUMINANCE8 ,GL_SLUMINANCE8_EXT , 0, GL_LUMINANCE ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A8L8 ,GL_LUMINANCE8_ALPHA8 ,GL_SLUMINANCE8_ALPHA8_EXT , 0, GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_A4L4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE4_ALPHA4 , 0, GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE + ,0 }, /* Bump mapping stuff */ - {WINED3DFMT_V8U8 ,GL_DSDT8_NV ,GL_DSDT8_NV ,GL_DSDT_NV ,GL_BYTE }, - {WINED3DFMT_L6V5U5 ,GL_DSDT8_MAG8_NV ,GL_DSDT8_MAG8_NV ,GL_DSDT_MAG_NV ,GL_BYTE }, - {WINED3DFMT_X8L8V8U8 ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT_MAG_VIB_NV ,GL_UNSIGNED_INT_8_8_S8_S8_REV_NV}, - {WINED3DFMT_Q8W8V8U8 ,GL_SIGNED_RGBA8_NV ,GL_SIGNED_RGBA8_NV ,GL_RGBA ,GL_BYTE }, - {WINED3DFMT_V16U16 ,GL_SIGNED_HILO16_NV ,GL_SIGNED_HILO16_NV ,GL_HILO_NV ,GL_SHORT }, - {WINED3DFMT_W11V11U10 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_A2W10V10U10 ,0 ,0 ,0 ,0 }, + {WINED3DFMT_V8U8 ,GL_DSDT8_NV ,GL_DSDT8_NV , 0, GL_DSDT_NV ,GL_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_L6V5U5 ,GL_DSDT8_MAG8_NV ,GL_DSDT8_MAG8_NV , 0, GL_DSDT_MAG_NV ,GL_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_X8L8V8U8 ,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_FILTERING }, + {WINED3DFMT_Q8W8V8U8 ,GL_SIGNED_RGBA8_NV ,GL_SIGNED_RGBA8_NV , 0, GL_RGBA ,GL_BYTE + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_V16U16 ,GL_SIGNED_HILO16_NV ,GL_SIGNED_HILO16_NV , 0, GL_HILO_NV ,GL_SHORT + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_W11V11U10 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_A2W10V10U10 ,0 ,0 , 0, 0 ,0 + ,0 }, /* Depth stencil formats */ - {WINED3DFMT_D16_LOCKABLE ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT }, - {WINED3DFMT_D32 ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT }, - {WINED3DFMT_D15S1 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT }, - {WINED3DFMT_D24S8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT }, - {WINED3DFMT_D24X8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT }, - {WINED3DFMT_D24X4S4 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT }, - {WINED3DFMT_D16 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT }, - {WINED3DFMT_L16 ,GL_LUMINANCE16_EXT ,GL_LUMINANCE16_EXT ,GL_LUMINANCE ,GL_UNSIGNED_SHORT }, - {WINED3DFMT_D32F_LOCKABLE ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT ,GL_FLOAT }, - {WINED3DFMT_D24FS8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_FLOAT }, + {WINED3DFMT_D16_LOCKABLE ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_DEPTH }, + {WINED3DFMT_D32 ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT + ,WINED3DFMT_FLAG_DEPTH }, + {WINED3DFMT_D15S1 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL }, + {WINED3DFMT_D24S8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT + ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL }, + {WINED3DFMT_D24X8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT + ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH }, + {WINED3DFMT_D24X4S4 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT + ,WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL }, + {WINED3DFMT_D16 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH }, + {WINED3DFMT_L16 ,GL_LUMINANCE16_EXT ,GL_LUMINANCE16_EXT , 0, GL_LUMINANCE ,GL_UNSIGNED_SHORT + ,WINED3DFMT_FLAG_FILTERING }, + {WINED3DFMT_D32F_LOCKABLE ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB , 0, GL_DEPTH_COMPONENT ,GL_FLOAT + ,WINED3DFMT_FLAG_DEPTH }, + {WINED3DFMT_D24FS8 ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB , 0, GL_DEPTH_COMPONENT ,GL_FLOAT + ,WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL}, /* Is this a vertex buffer? */ - {WINED3DFMT_VERTEXDATA ,0 ,0 ,0 ,0 }, - {WINED3DFMT_INDEX16 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_INDEX32 ,0 ,0 ,0 ,0 }, - {WINED3DFMT_Q16W16V16U16 ,GL_COLOR_INDEX ,GL_COLOR_INDEX ,GL_COLOR_INDEX ,GL_UNSIGNED_SHORT } + {WINED3DFMT_VERTEXDATA ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_INDEX16 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_INDEX32 ,0 ,0 , 0, 0 ,0 + ,0 }, + {WINED3DFMT_Q16W16V16U16 ,GL_COLOR_INDEX ,GL_COLOR_INDEX , 0, GL_COLOR_INDEX ,GL_UNSIGNED_SHORT + ,0 }, + /* Vendor-specific formats */ + {WINED3DFMT_ATI2N ,0 ,0 , 0, GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE + ,0 }, + {WINED3DFMT_NVHU ,0 ,0 , 0, GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE + ,0 }, + {WINED3DFMT_NVHS ,0 ,0 , 0, GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE + ,0 } }; static inline int getFmtIdx(WINED3DFORMAT fmt) { @@ -228,6 +319,48 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info) gl_info->gl_formats[dst].glFormat = gl_formats_template[src].glFormat; gl_info->gl_formats[dst].glType = gl_formats_template[src].glType; gl_info->gl_formats[dst].conversion_group= WINED3DFMT_UNKNOWN; + gl_info->gl_formats[dst].Flags = gl_formats_template[src].Flags; + gl_info->gl_formats[dst].heightscale = 1.0; + + if(wined3d_settings.offscreen_rendering_mode == ORM_FBO && + gl_formats_template[src].rtInternal != 0) { + GLuint tex, fb; + GLenum status; + + /* Check if the default internal format is supported as a frame buffer target, otherwise + * fall back to the render target internal. + * + * Try to stick to the standard format if possible, this limits precision differences + */ + while(glGetError()); + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, gl_formats_template[src].glInternal, 16, 16, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + GL_EXTCALL(glGenFramebuffersEXT(1, &fb)); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb)); + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, tex, 0)); + + status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); + GL_EXTCALL(glDeleteFramebuffersEXT(1, &fb)); + glDeleteTextures(1, &tex); + + checkGLcall("Framebuffer format check"); + + if(status != GL_FRAMEBUFFER_COMPLETE_EXT) { + TRACE("Internal format of %s not supported as frame buffer target, using render target internal instead\n", + debug_d3dformat(gl_formats_template[src].fmt)); + gl_info->gl_formats[dst].rtInternal = gl_formats_template[src].rtInternal; + } else { + TRACE("Format %s is supported as fbo target\n", debug_d3dformat(gl_formats_template[src].fmt)); + gl_info->gl_formats[dst].rtInternal = gl_formats_template[src].glInternal; + } + + } else { + gl_info->gl_formats[dst].rtInternal = gl_formats_template[src].glInternal; + } } /* V8U8 is supported natively by GL_ATI_envmap_bumpmap and GL_NV_texture_shader. @@ -251,12 +384,12 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info) gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V16U16; } else { /* Blue = 1.0 fixup, disabled for now */ -#if 0 - dst = getFmtIdx(WINED3DFMT_V8U8); - gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; - dst = getFmtIdx(WINED3DFMT_V16U16); - gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; -#endif + if(0) { + dst = getFmtIdx(WINED3DFMT_V8U8); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; + dst = getFmtIdx(WINED3DFMT_V16U16); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; + } } if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { @@ -277,8 +410,72 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info) */ } + if(GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { + dst = getFmtIdx(WINED3DFMT_ATI2N); + gl_info->gl_formats[dst].glInternal = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; + gl_info->gl_formats[dst].glGammaInternal = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; + gl_info->gl_formats[dst].conversion_group= WINED3DFMT_ATI2N; + } else if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC)) { + dst = getFmtIdx(WINED3DFMT_ATI2N); + gl_info->gl_formats[dst].glInternal = GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; + gl_info->gl_formats[dst].glGammaInternal = GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; + gl_info->gl_formats[dst].conversion_group= WINED3DFMT_ATI2N; + } + + if(!GL_SUPPORT(APPLE_YCBCR_422)) { + dst = getFmtIdx(WINED3DFMT_YUY2); + gl_info->gl_formats[dst].glInternal = GL_LUMINANCE_ALPHA; + gl_info->gl_formats[dst].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */ + gl_info->gl_formats[dst].glFormat = GL_LUMINANCE_ALPHA; + gl_info->gl_formats[dst].glType = GL_UNSIGNED_BYTE; + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_YUY2; + + dst = getFmtIdx(WINED3DFMT_UYVY); + gl_info->gl_formats[dst].glInternal = GL_LUMINANCE_ALPHA; + gl_info->gl_formats[dst].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */ + gl_info->gl_formats[dst].glFormat = GL_LUMINANCE_ALPHA; + gl_info->gl_formats[dst].glType = GL_UNSIGNED_BYTE; + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_UYVY; + } + + dst = getFmtIdx(WINED3DFMT_YV12); + gl_info->gl_formats[dst].heightscale = 1.5; + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_YV12; + return TRUE; } + +/* NOTE: Make sure these are in the correct numerical order. (see /include/wined3d_types.h) */ +static WINED3DGLTYPE const glTypeLookupTemplate[WINED3DDECLTYPE_UNUSED] = { + {WINED3DDECLTYPE_FLOAT1, 1, GL_FLOAT , GL_FALSE ,sizeof(float)}, + {WINED3DDECLTYPE_FLOAT2, 2, GL_FLOAT , GL_FALSE ,sizeof(float)}, + {WINED3DDECLTYPE_FLOAT3, 3, GL_FLOAT , GL_FALSE ,sizeof(float)}, + {WINED3DDECLTYPE_FLOAT4, 4, GL_FLOAT , GL_FALSE ,sizeof(float)}, + {WINED3DDECLTYPE_D3DCOLOR, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)}, + {WINED3DDECLTYPE_UBYTE4, 4, GL_UNSIGNED_BYTE , GL_FALSE ,sizeof(BYTE)}, + {WINED3DDECLTYPE_SHORT2, 2, GL_SHORT , GL_FALSE ,sizeof(short int)}, + {WINED3DDECLTYPE_SHORT4, 4, GL_SHORT , GL_FALSE ,sizeof(short int)}, + {WINED3DDECLTYPE_UBYTE4N, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)}, + {WINED3DDECLTYPE_SHORT2N, 2, GL_SHORT , GL_TRUE ,sizeof(short int)}, + {WINED3DDECLTYPE_SHORT4N, 4, GL_SHORT , GL_TRUE ,sizeof(short int)}, + {WINED3DDECLTYPE_USHORT2N, 2, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)}, + {WINED3DDECLTYPE_USHORT4N, 4, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)}, + {WINED3DDECLTYPE_UDEC3, 3, GL_UNSIGNED_SHORT , GL_FALSE ,sizeof(short int)}, + {WINED3DDECLTYPE_DEC3N, 3, GL_SHORT , GL_TRUE ,sizeof(short int)}, + {WINED3DDECLTYPE_FLOAT16_2, 2, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)}, + {WINED3DDECLTYPE_FLOAT16_4, 4, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)}}; + +void init_type_lookup(WineD3D_GL_Info *gl_info) { + memcpy(gl_info->glTypeLookup, glTypeLookupTemplate, sizeof(glTypeLookupTemplate)); + if(!GL_SUPPORT(NV_HALF_FLOAT)) { + /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though. + * It is the job of the vertex buffer code to make sure that the vbos have the right format + */ + gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_2].glType = GL_FLOAT; + gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_4].glType = GL_FLOAT; + } +} + #undef GLINFO_LOCATION #define GLINFO_LOCATION This->adapter->gl_info @@ -293,11 +490,16 @@ const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, WineD3D_GL_In idx = getFmtIdx(WINED3DFMT_UNKNOWN); } if(glDesc) { - if(!gl_info) { - ERR("OpenGL pixel format information was requested, but no gl info structure passed\n"); - return NULL; + if(!gl_info->gl_formats) { + /* If we do not have gl format information, provide a dummy NULL format. This is an easy way to make + * all gl caps check return "unsupported" than catching the lack of gl all over the code. ANSI C requires + * static variables to be initialized to 0. + */ + static const GlPixelFormatDesc dummyFmt; + *glDesc = &dummyFmt; + } else { + *glDesc = &gl_info->gl_formats[idx]; } - *glDesc = &gl_info->gl_formats[idx]; } return &formats[idx]; } @@ -340,6 +542,7 @@ const char* debug_d3dformat(WINED3DFORMAT fmt) { FMT_TO_STR(WINED3DFMT_A2W10V10U10); FMT_TO_STR(WINED3DFMT_UYVY); FMT_TO_STR(WINED3DFMT_YUY2); + FMT_TO_STR(WINED3DFMT_YV12); FMT_TO_STR(WINED3DFMT_DXT1); FMT_TO_STR(WINED3DFMT_DXT2); FMT_TO_STR(WINED3DFMT_DXT3); @@ -369,6 +572,9 @@ const char* debug_d3dformat(WINED3DFORMAT fmt) { FMT_TO_STR(WINED3DFMT_G32R32F); FMT_TO_STR(WINED3DFMT_A32B32G32R32F); FMT_TO_STR(WINED3DFMT_CxV8U8); + FMT_TO_STR(WINED3DFMT_ATI2N); + FMT_TO_STR(WINED3DFMT_NVHU); + FMT_TO_STR(WINED3DFMT_NVHS); #undef FMT_TO_STR default: { @@ -792,7 +998,7 @@ const char* debug_d3dtexturestate(DWORD state) { } } -static const char* debug_d3dtop(WINED3DTEXTUREOP d3dtop) { +const char* debug_d3dtop(WINED3DTEXTUREOP d3dtop) { switch (d3dtop) { #define D3DTOP_TO_STR(u) case u: return #u D3DTOP_TO_STR(WINED3DTOP_DISABLE); @@ -803,6 +1009,7 @@ static const char* debug_d3dtop(WINED3DTEXTUREOP d3dtop) { D3DTOP_TO_STR(WINED3DTOP_MODULATE4X); D3DTOP_TO_STR(WINED3DTOP_ADD); D3DTOP_TO_STR(WINED3DTOP_ADDSIGNED); + D3DTOP_TO_STR(WINED3DTOP_ADDSIGNED2X); D3DTOP_TO_STR(WINED3DTOP_SUBTRACT); D3DTOP_TO_STR(WINED3DTOP_ADDSMOOTH); D3DTOP_TO_STR(WINED3DTOP_BLENDDIFFUSEALPHA); @@ -956,70 +1163,7 @@ GLenum CompareFunc(DWORD func) { } } -static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) { - switch (d3dta) { - case WINED3DTA_DIFFUSE: - return GL_PRIMARY_COLOR_NV; - - case WINED3DTA_CURRENT: - if (stage) return GL_SPARE0_NV; - else return GL_PRIMARY_COLOR_NV; - - case WINED3DTA_TEXTURE: - if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx; - else return GL_PRIMARY_COLOR_NV; - - case WINED3DTA_TFACTOR: - return GL_CONSTANT_COLOR0_NV; - - case WINED3DTA_SPECULAR: - return GL_SECONDARY_COLOR_NV; - - case WINED3DTA_TEMP: - /* TODO: Support WINED3DTSS_RESULTARG */ - FIXME("WINED3DTA_TEMP, not properly supported.\n"); - return GL_SPARE1_NV; - - case WINED3DTA_CONSTANT: - /* TODO: Support per stage constants (WINED3DTSS_CONSTANT, NV_register_combiners2) */ - FIXME("WINED3DTA_CONSTANT, not properly supported.\n"); - return GL_CONSTANT_COLOR1_NV; - - default: - FIXME("Unrecognized texture arg %#x\n", d3dta); - return GL_TEXTURE; - } -} - -static GLenum invert_mapping(GLenum mapping) { - if (mapping == GL_UNSIGNED_INVERT_NV) return GL_SIGNED_IDENTITY_NV; - else if (mapping == GL_SIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV; - - FIXME("Unhandled mapping %#x\n", mapping); - return mapping; -} - -static void get_src_and_opr_nvrc(DWORD stage, DWORD arg, BOOL is_alpha, GLenum* input, GLenum* mapping, GLenum *component_usage, INT texture_idx) { - /* The WINED3DTA_COMPLEMENT flag specifies the complement of the input should - * be used. */ - if (arg & WINED3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV; - else *mapping = GL_SIGNED_IDENTITY_NV; - - /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the input - * should be used for all input components. */ - if (is_alpha || arg & WINED3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA; - else *component_usage = GL_RGB; - - *input = d3dta_to_combiner_input(arg & WINED3DTA_SELECTMASK, stage, texture_idx); -} - -typedef struct { - GLenum input[3]; - GLenum mapping[3]; - GLenum component_usage[3]; -} tex_op_args; - -static BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) { +BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) { if (op == WINED3DTOP_DISABLE) return FALSE; if (This->stateBlock->textures[stage]) return FALSE; @@ -1033,1443 +1177,9 @@ static BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP return FALSE; } -void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface; - tex_op_args tex_op_args = {{0}, {0}, {0}}; - GLenum portion = is_alpha ? GL_ALPHA : GL_RGB; - GLenum target = GL_COMBINER0_NV + stage; - - 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); - - /* If a texture stage references an invalid texture unit the stage just - * passes through the result from the previous stage */ - if (is_invalid_op(This, stage, op, arg1, arg2, arg3)) { - arg1 = WINED3DTA_CURRENT; - op = WINED3DTOP_SELECTARG1; - } - - get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0], - &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx); - get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1], - &tex_op_args.mapping[1], &tex_op_args.component_usage[1], texture_idx); - get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2], - &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx); - - - /* This is called by a state handler which has the gl lock held and a context for the thread */ - switch(op) - { - case WINED3DTOP_DISABLE: - /* Only for alpha */ - if (!is_alpha) ERR("Shouldn't be called for WINED3DTSS_COLOROP (WINED3DTOP_DISABLE)\n"); - /* Input, prev_alpha*1 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_SELECTARG1: - case WINED3DTOP_SELECTARG2: - /* Input, arg*1 */ - if (op == WINED3DTOP_SELECTARG1) { - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - } else { - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - } - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_MODULATE: - case WINED3DTOP_MODULATE2X: - case WINED3DTOP_MODULATE4X: - /* Input, arg1*arg2 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - - /* Output */ - if (op == WINED3DTOP_MODULATE) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - } else if (op == WINED3DTOP_MODULATE2X) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - } else if (op == WINED3DTOP_MODULATE4X) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - } - break; - - case WINED3DTOP_ADD: - case WINED3DTOP_ADDSIGNED: - case WINED3DTOP_ADDSIGNED2X: - /* Input, arg1*1+arg2*1 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - if (op == WINED3DTOP_ADD) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - } else if (op == WINED3DTOP_ADDSIGNED) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); - } else if (op == WINED3DTOP_ADDSIGNED2X) { - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); - } - break; - - case WINED3DTOP_SUBTRACT: - /* Input, arg1*1+-arg2*1 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[1], GL_SIGNED_NEGATE_NV, tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_ADDSMOOTH: - /* Input, arg1*1+(1-arg1)*arg2 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_BLENDDIFFUSEALPHA: - case WINED3DTOP_BLENDTEXTUREALPHA: - case WINED3DTOP_BLENDFACTORALPHA: - case WINED3DTOP_BLENDTEXTUREALPHAPM: - case WINED3DTOP_BLENDCURRENTALPHA: - { - GLenum alpha_src = GL_PRIMARY_COLOR_NV; - if (op == WINED3DTOP_BLENDDIFFUSEALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_DIFFUSE, stage, texture_idx); - else if (op == WINED3DTOP_BLENDTEXTUREALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx); - else if (op == WINED3DTOP_BLENDFACTORALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TFACTOR, stage, texture_idx); - else if (op == WINED3DTOP_BLENDTEXTUREALPHAPM) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx); - else if (op == WINED3DTOP_BLENDCURRENTALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_CURRENT, stage, texture_idx); - else FIXME("Unhandled WINED3DTOP %s, shouldn't happen\n", debug_d3dtop(op)); - - /* Input, arg1*alpha_src+arg2*(1-alpha_src) */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - if (op == WINED3DTOP_BLENDTEXTUREALPHAPM) - { - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - } else { - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - alpha_src, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA)); - } - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - alpha_src, GL_UNSIGNED_INVERT_NV, GL_ALPHA)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - } - - case WINED3DTOP_MODULATEALPHA_ADDCOLOR: - /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */ - if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEALPHA_ADDCOLOR)\n"); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_MODULATECOLOR_ADDALPHA: - /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */ - if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATECOLOR_ADDALPHA)\n"); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: - /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */ - if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVALPHA_ADDCOLOR)\n"); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), GL_ALPHA)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: - /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */ - if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVCOLOR_ADDALPHA)\n"); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_DOTPRODUCT3: - /* Input, arg1 . arg2 */ - /* FIXME: DX7 uses a different calculation? */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[1])); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_MULTIPLYADD: - /* Input, arg1*1+arg2*arg3 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_LERP: - /* Input, arg1*arg2+(1-arg1)*arg3 */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV, - tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV, - tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); - - /* Output */ - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - - case WINED3DTOP_BUMPENVMAPLUMINANCE: - case WINED3DTOP_BUMPENVMAP: - if(GL_SUPPORT(NV_TEXTURE_SHADER)) { - /* The bump map stage itself isn't exciting, just read the texture. But tell the next stage to - * perform bump mapping and source from the current stage. Pretty much a SELECTARG2. - * ARG2 is passed through unmodified(apps will most likely use D3DTA_CURRENT for arg2, arg1 - * (which will most likely be D3DTA_TEXTURE) is available as a texture shader input for the next stage - */ - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV, - tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1])); - GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV, - GL_ZERO, GL_UNSIGNED_INVERT_NV, portion)); - GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, - GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); - break; - } - - default: - FIXME("Unhandled WINED3DTOP: stage %d, is_alpha %d, op %s (%#x), arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n", - stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx); - } - - checkGLcall("set_tex_op_nvrc()\n"); - -} - -static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) { - /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the - * input should be used for all input components. The WINED3DTA_COMPLEMENT - * flag specifies the complement of the input should be used. */ - BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE; - BOOL complement = arg & WINED3DTA_COMPLEMENT; - - /* Calculate the operand */ - if (complement) { - if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA; - else *operand = GL_ONE_MINUS_SRC_COLOR; - } else { - if (from_alpha) *operand = GL_SRC_ALPHA; - else *operand = GL_SRC_COLOR; - } - - /* Calculate the source */ - switch (arg & WINED3DTA_SELECTMASK) { - case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break; - case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break; - case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break; - case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break; - case WINED3DTA_SPECULAR: - /* - * According to the GL_ARB_texture_env_combine specs, SPECULAR is - * 'Secondary color' and isn't supported until base GL supports it - * There is no concept of temp registers as far as I can tell - */ - FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n"); - *source = GL_TEXTURE; - break; - default: - FIXME("Unrecognized texture arg %#x\n", arg); - *source = GL_TEXTURE; - break; - } -} - -/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/ -#if defined (GL_VERSION_1_3) -# define useext(A) A -# define combine_ext 1 -#elif defined (GL_EXT_texture_env_combine) -# define useext(A) A##_EXT -# define combine_ext 1 -#elif defined (GL_ARB_texture_env_combine) -# define useext(A) A##_ARB -# define combine_ext 1 -#else -# undef combine_ext -#endif - -#if !defined(combine_ext) -void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) -{ - FIXME("Requires opengl combine extensions to work\n"); - return; -} -#else -/* Setup the texture operations texture stage states */ -void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) -{ - GLenum src1, src2, src3; - GLenum opr1, opr2, opr3; - GLenum comb_target; - GLenum src0_target, src1_target, src2_target; - GLenum opr0_target, opr1_target, opr2_target; - GLenum scal_target; - GLenum opr=0, invopr, src3_target, opr3_target; - BOOL Handled = FALSE; - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3); - - /* This is called by a state handler which has the gl lock held and a context for the thread */ - - /* Note: Operations usually involve two ars, src0 and src1 and are operations of - the form (a1 a2). However, some of the more complex operations - take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added - in a third parameter called a0. Therefore these are operations of the form - a0 a1 a2, ie the new parameter goes to the front. - - However, below we treat the new (a0) parameter as src2/opr2, so in the actual - functions below, expect their syntax to differ slightly to those listed in the - manuals, ie replace arg1 with arg3, arg2 with arg1 and arg3 with arg2 - This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */ - - if (isAlpha) { - comb_target = useext(GL_COMBINE_ALPHA); - src0_target = useext(GL_SOURCE0_ALPHA); - src1_target = useext(GL_SOURCE1_ALPHA); - src2_target = useext(GL_SOURCE2_ALPHA); - opr0_target = useext(GL_OPERAND0_ALPHA); - opr1_target = useext(GL_OPERAND1_ALPHA); - opr2_target = useext(GL_OPERAND2_ALPHA); - scal_target = GL_ALPHA_SCALE; - } - else { - comb_target = useext(GL_COMBINE_RGB); - src0_target = useext(GL_SOURCE0_RGB); - src1_target = useext(GL_SOURCE1_RGB); - src2_target = useext(GL_SOURCE2_RGB); - opr0_target = useext(GL_OPERAND0_RGB); - opr1_target = useext(GL_OPERAND1_RGB); - opr2_target = useext(GL_OPERAND2_RGB); - scal_target = useext(GL_RGB_SCALE); - } - - /* If a texture stage references an invalid texture unit the stage just - * passes through the result from the previous stage */ - if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) { - arg1 = WINED3DTA_CURRENT; - op = WINED3DTOP_SELECTARG1; - } - - /* From MSDN (WINED3DTSS_ALPHAARG1) : - The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage, - then the default argument is WINED3DTA_DIFFUSE. - FIXME? If texture added/removed, may need to reset back as well? */ - if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) { - get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1); - } else { - get_src_and_opr(arg1, isAlpha, &src1, &opr1); - } - get_src_and_opr(arg2, isAlpha, &src2, &opr2); - get_src_and_opr(arg3, isAlpha, &src3, &opr3); - - TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3); - - Handled = TRUE; /* Assume will be handled */ - - /* Other texture operations require special extensions: */ - if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { - if (isAlpha) { - opr = GL_SRC_ALPHA; - invopr = GL_ONE_MINUS_SRC_ALPHA; - src3_target = GL_SOURCE3_ALPHA_NV; - opr3_target = GL_OPERAND3_ALPHA_NV; - } else { - opr = GL_SRC_COLOR; - invopr = GL_ONE_MINUS_SRC_COLOR; - src3_target = GL_SOURCE3_RGB_NV; - opr3_target = GL_OPERAND3_RGB_NV; - } - switch (op) { - case WINED3DTOP_DISABLE: /* Only for alpha */ - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); - break; - case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */ - case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */ - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - if (op == WINED3DTOP_SELECTARG1) { - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - } else { - glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); - checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); - } - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); - break; - - case WINED3DTOP_MODULATE: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATE2X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); - checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); - break; - case WINED3DTOP_MODULATE4X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); - checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); - break; - - case WINED3DTOP_ADD: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - - case WINED3DTOP_ADDSIGNED: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - - case WINED3DTOP_ADDSIGNED2X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); - checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); - break; - - case WINED3DTOP_ADDSMOOTH: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); - checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - - case WINED3DTOP_BLENDDIFFUSEALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)); - checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)); - checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDTEXTUREALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDFACTORALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)); - checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)); - checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDTEXTUREALPHAPM: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATEALPHA_ADDCOLOR: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */ - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */ - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */ - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */ - glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); - checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); - switch (opr) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATECOLOR_ADDALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); - checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); - checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); - checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MULTIPLYADD: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); - checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, src2); - checkGLcall("GL_TEXTURE_ENV, src3_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - - case WINED3DTOP_BUMPENVMAP: - { - } - - case WINED3DTOP_BUMPENVMAPLUMINANCE: - FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n"); - - default: - Handled = FALSE; - } - if (Handled) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); - checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV"); - - return; - } - } /* GL_NV_texture_env_combine4 */ - - Handled = TRUE; /* Again, assume handled */ - switch (op) { - case WINED3DTOP_DISABLE: /* Only for alpha */ - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); - checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_SELECTARG1: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_SELECTARG2: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); - checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATE: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_MODULATE2X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); - checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); - break; - case WINED3DTOP_MODULATE4X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); - checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); - break; - case WINED3DTOP_ADD: - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_ADDSIGNED: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_ADDSIGNED2X: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); - checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); - break; - case WINED3DTOP_SUBTRACT: - if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else { - FIXME("This version of opengl does not support GL_SUBTRACT\n"); - } - break; - - case WINED3DTOP_BLENDDIFFUSEALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR)); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDTEXTUREALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDFACTORALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT)); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_BLENDCURRENTALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS)); - checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_DOTPRODUCT3: - if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB"); - } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT"); - } else { - FIXME("This version of opengl does not support GL_DOT3\n"); - } - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_LERP: - glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); - checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); - checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src3); - checkGLcall("GL_TEXTURE_ENV, src2_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - break; - case WINED3DTOP_ADDSMOOTH: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_BLENDTEXTUREALPHAPM: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE); - checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA); - checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_MODULATEALPHA_ADDCOLOR: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_MODULATECOLOR_ADDALPHA: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; - case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - switch (opr1) { - case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; - case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; - } - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_MULTIPLYADD: - if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) { - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); - checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); - checkGLcall("GL_TEXTURE_ENV, src0_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); - checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); - } else - Handled = FALSE; - break; - case WINED3DTOP_BUMPENVMAPLUMINANCE: - if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { - /* Some apps use BUMPENVMAPLUMINANCE instead of D3DTOP_BUMPENVMAP, although - * they check for the non-luminance cap flag. Well, give them what they asked - * for :-) - */ - WARN("Application uses WINED3DTOP_BUMPENVMAPLUMINANCE\n"); - } else { - Handled = FALSE; - break; - } - /* Fall through */ - case WINED3DTOP_BUMPENVMAP: - if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { - TRACE("Using ati bumpmap on stage %d, target %d\n", Stage, Stage + 1); - glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI); - checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI)"); - glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1); - checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); - checkGLcall("GL_TEXTURE_ENV, src0_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); - checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); - checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); - checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); - checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - - Handled = TRUE; - break; - } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - /* Technically texture shader support without register combiners is possible, but not expected to occur - * on real world cards, so for now a fixme should be enough - */ - FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n"); - } - default: - Handled = FALSE; - } - - if (Handled) { - BOOL combineOK = TRUE; - if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) { - DWORD op2; - - if (isAlpha) { - op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP]; - } else { - op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP]; - } - - /* Note: If COMBINE4 in effect can't go back to combine! */ - switch (op2) { - case WINED3DTOP_ADDSMOOTH: - case WINED3DTOP_BLENDTEXTUREALPHAPM: - case WINED3DTOP_MODULATEALPHA_ADDCOLOR: - case WINED3DTOP_MODULATECOLOR_ADDALPHA: - case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: - case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: - case WINED3DTOP_MULTIPLYADD: - /* Ignore those implemented in both cases */ - switch (op) { - case WINED3DTOP_SELECTARG1: - case WINED3DTOP_SELECTARG2: - combineOK = FALSE; - Handled = FALSE; - break; - default: - FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha); - return; - } - } - } - - if (combineOK) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); - checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); - - return; - } - } - - /* After all the extensions, if still unhandled, report fixme */ - FIXME("Unhandled texture operation %s\n", debug_d3dtop(op)); - #undef GLINFO_LOCATION -} -#endif - /* Setup this textures matrix according to the texture flags*/ -void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype) +void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype, + BOOL ffp_proj_control) { float mat[16]; @@ -2490,15 +1200,17 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, B memcpy(mat, smat, 16 * sizeof(float)); if (flags & WINED3DTTFF_PROJECTED) { - switch (flags & ~WINED3DTTFF_PROJECTED) { - case WINED3DTTFF_COUNT2: - mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13]; - mat[1] = mat[5] = mat[9] = mat[13] = 0; - break; - case WINED3DTTFF_COUNT3: - mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14]; - mat[2] = mat[6] = mat[10] = mat[14] = 0; - break; + if(!ffp_proj_control) { + switch (flags & ~WINED3DTTFF_PROJECTED) { + case WINED3DTTFF_COUNT2: + mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13]; + mat[1] = mat[5] = mat[9] = mat[13] = 0; + break; + case WINED3DTTFF_COUNT3: + mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14]; + mat[2] = mat[6] = mat[10] = mat[14] = 0; + break; + } } } else { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */ if(!calculatedCoords) { @@ -2524,7 +1236,7 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, B case WINED3DDECLTYPE_FLOAT3: /* Opengl defaults match dx defaults */ case WINED3DDECLTYPE_FLOAT4: /* No defaults apply, all app defined */ - /* This is to prevent swaping the matrix lines and put the default 4th coord = 1.0 + /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0 * into a bad place. The division elimination below will apply to make sure the * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0 */ @@ -2534,29 +1246,32 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, B FIXME("Unexpected fixed function texture coord input\n"); } } - switch (flags & ~WINED3DTTFF_PROJECTED) { - /* case WINED3DTTFF_COUNT1: Won't ever get here */ - case WINED3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0; - /* OpenGL divides the first 3 vertex coord by the 4th by default, - * which is essentially the same as D3DTTFF_PROJECTED. Make sure that - * the 4th coord evaluates to 1.0 to eliminate that. - * - * If the fixed function pipeline is used, the 4th value remains unused, - * so there is no danger in doing this. With vertex shaders we have a - * problem. Should an app hit that problem, the code here would have to - * check for pixel shaders, and the shader has to undo the default gl divide. - * - * A more serious problem occurs if the app passes 4 coordinates in, and the - * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow - * or a replacement shader - */ - default: mat[3] = mat[7] = mat[11] = 0; mat[15] = 1; + if(!ffp_proj_control) { + switch (flags & ~WINED3DTTFF_PROJECTED) { + /* case WINED3DTTFF_COUNT1: Won't ever get here */ + case WINED3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0; + /* OpenGL divides the first 3 vertex coord by the 4th by default, + * which is essentially the same as D3DTTFF_PROJECTED. Make sure that + * the 4th coord evaluates to 1.0 to eliminate that. + * + * If the fixed function pipeline is used, the 4th value remains unused, + * so there is no danger in doing this. With vertex shaders we have a + * problem. Should an app hit that problem, the code here would have to + * check for pixel shaders, and the shader has to undo the default gl divide. + * + * A more serious problem occurs if the app passes 4 coordinates in, and the + * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow + * or a replacement shader + */ + default: mat[3] = mat[7] = mat[11] = 0; mat[15] = 1; + } } } glLoadMatrixf(mat); checkGLcall("glLoadMatrixf(mat)"); } +#undef GLINFO_LOCATION #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info @@ -2630,6 +1345,7 @@ BOOL getDepthStencilBits(WINED3DFORMAT fmt, short *depthSize, short *stencilSize case WINED3DFMT_D24S8: case WINED3DFMT_D24FS8: case WINED3DFMT_D32: + case WINED3DFMT_D32F_LOCKABLE: break; default: FIXME("Unsupported stencil format: %s\n", debug_d3dformat(fmt)); @@ -2657,8 +1373,8 @@ WINED3DFORMAT pixelformat_for_depth(DWORD depth) { case 8: return WINED3DFMT_P8; case 15: return WINED3DFMT_X1R5G5B5; case 16: return WINED3DFMT_R5G6B5; - case 24: return WINED3DFMT_R8G8B8; - case 32: return WINED3DFMT_X8R8G8B8; + case 24: return WINED3DFMT_X8R8G8B8; /* Robots needs 24bit to be X8R8G8B8 */ + case 32: return WINED3DFMT_X8R8G8B8; /* EVE online and the Fur demo need 32bit AdapterDisplayMode to return X8R8G8B8 */ default: return WINED3DFMT_UNKNOWN; } } @@ -2757,10 +1473,17 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4] /* No oversized texture? This is easy */ if(!(This->Flags & SFLAG_OVERSIZE)) { /* Which rect from the texture do I need? */ - 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; + if(This->glDescription.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 { @@ -2837,7 +1560,10 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4] 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 + * 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); @@ -2850,12 +1576,12 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4] /* Hash table functions */ -hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function) +struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function) { - hash_table_t *table; + struct hash_table_t *table; unsigned int initial_size = 8; - table = HeapAlloc(GetProcessHeap(), 0, sizeof(hash_table_t) + (initial_size * sizeof(struct list))); + table = HeapAlloc(GetProcessHeap(), 0, sizeof(struct hash_table_t) + (initial_size * sizeof(struct list))); if (!table) { ERR("Failed to allocate table, returning NULL.\n"); @@ -2877,7 +1603,7 @@ hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function } table->bucket_count = initial_size; - table->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, table->grow_size * sizeof(hash_table_entry_t)); + table->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, table->grow_size * sizeof(struct hash_table_entry_t)); if (!table->entries) { ERR("Failed to allocate table entries, returning NULL.\n"); @@ -2893,12 +1619,15 @@ hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function return table; } -void hash_table_destroy(hash_table_t *table) +void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb) { unsigned int i = 0; for (i = 0; i < table->entry_count; ++i) { + if(free_value) { + free_value(table->entries[i].value, cb); + } HeapFree(GetProcessHeap(), 0, table->entries[i].key); } @@ -2907,21 +1636,21 @@ void hash_table_destroy(hash_table_t *table) HeapFree(GetProcessHeap(), 0, table); } -static inline hash_table_entry_t *hash_table_get_by_idx(hash_table_t *table, void *key, unsigned int idx) +static inline struct hash_table_entry_t *hash_table_get_by_idx(struct hash_table_t *table, void *key, unsigned int idx) { - hash_table_entry_t *entry; + struct hash_table_entry_t *entry; if (table->buckets[idx].next) - LIST_FOR_EACH_ENTRY(entry, &(table->buckets[idx]), hash_table_entry_t, entry) + LIST_FOR_EACH_ENTRY(entry, &(table->buckets[idx]), struct hash_table_entry_t, entry) if (table->compare_function(entry->key, key)) return entry; return NULL; } -static BOOL hash_table_resize(hash_table_t *table, unsigned int new_bucket_count) +static BOOL hash_table_resize(struct hash_table_t *table, unsigned int new_bucket_count) { unsigned int new_entry_count = 0; - hash_table_entry_t *new_entries; + struct hash_table_entry_t *new_entries; struct list *new_buckets; unsigned int grow_size = new_bucket_count - (new_bucket_count >> 2); unsigned int i; @@ -2933,7 +1662,7 @@ static BOOL hash_table_resize(hash_table_t *table, unsigned int new_bucket_count return FALSE; } - new_entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, grow_size * sizeof(hash_table_entry_t)); + new_entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, grow_size * sizeof(struct hash_table_entry_t)); if (!new_entries) { ERR("Failed to allocate new entries, returning FALSE.\n"); @@ -2945,12 +1674,12 @@ static BOOL hash_table_resize(hash_table_t *table, unsigned int new_bucket_count { if (table->buckets[i].next) { - hash_table_entry_t *entry, *entry2; + struct hash_table_entry_t *entry, *entry2; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &table->buckets[i], hash_table_entry_t, entry) + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &table->buckets[i], struct hash_table_entry_t, entry) { int j; - hash_table_entry_t *new_entry = new_entries + (new_entry_count++); + struct hash_table_entry_t *new_entry = new_entries + (new_entry_count++); *new_entry = *entry; j = new_entry->hash & (new_bucket_count - 1); @@ -2977,11 +1706,11 @@ static BOOL hash_table_resize(hash_table_t *table, unsigned int new_bucket_count return TRUE; } -void hash_table_put(hash_table_t *table, void *key, void *value) +void hash_table_put(struct hash_table_t *table, void *key, void *value) { unsigned int idx; unsigned int hash; - hash_table_entry_t *entry; + struct hash_table_entry_t *entry; hash = table->hash_function(key); idx = hash & (table->bucket_count - 1); @@ -3035,7 +1764,7 @@ void hash_table_put(hash_table_t *table, void *key, void *value) struct list *elem = list_head(&table->free_entries); list_remove(elem); - entry = LIST_ENTRY(elem, hash_table_entry_t, entry); + entry = LIST_ENTRY(elem, struct hash_table_entry_t, entry); } else { entry = table->entries + (table->entry_count++); } @@ -3050,18 +1779,380 @@ void hash_table_put(hash_table_t *table, void *key, void *value) ++table->count; } -void hash_table_remove(hash_table_t *table, void *key) +void hash_table_remove(struct hash_table_t *table, void *key) { hash_table_put(table, key, NULL); } -void *hash_table_get(hash_table_t *table, void *key) +void *hash_table_get(struct hash_table_t *table, void *key) { unsigned int idx; - hash_table_entry_t *entry; + struct hash_table_entry_t *entry; idx = table->hash_function(key) & (table->bucket_count - 1); entry = hash_table_get_by_idx(table, key, idx); return entry ? entry->value : NULL; } + +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *settings, BOOL ignore_textype) { +#define ARG1 0x01 +#define ARG2 0x02 +#define ARG0 0x04 + static const unsigned char args[WINED3DTOP_LERP + 1] = { + /* undefined */ 0, + /* D3DTOP_DISABLE */ 0, + /* D3DTOP_SELECTARG1 */ ARG1, + /* D3DTOP_SELECTARG2 */ ARG2, + /* D3DTOP_MODULATE */ ARG1 | ARG2, + /* D3DTOP_MODULATE2X */ ARG1 | ARG2, + /* D3DTOP_MODULATE4X */ ARG1 | ARG2, + /* D3DTOP_ADD */ ARG1 | ARG2, + /* D3DTOP_ADDSIGNED */ ARG1 | ARG2, + /* D3DTOP_ADDSIGNED2X */ ARG1 | ARG2, + /* D3DTOP_SUBTRACT */ ARG1 | ARG2, + /* D3DTOP_ADDSMOOTH */ ARG1 | ARG2, + /* D3DTOP_BLENDDIFFUSEALPHA */ ARG1 | ARG2, + /* D3DTOP_BLENDTEXTUREALPHA */ ARG1 | ARG2, + /* D3DTOP_BLENDFACTORALPHA */ ARG1 | ARG2, + /* D3DTOP_BLENDTEXTUREALPHAPM */ ARG1 | ARG2, + /* D3DTOP_BLENDCURRENTALPHA */ ARG1 | ARG2, + /* D3DTOP_PREMODULATE */ ARG1 | ARG2, + /* D3DTOP_MODULATEALPHA_ADDCOLOR */ ARG1 | ARG2, + /* D3DTOP_MODULATECOLOR_ADDALPHA */ ARG1 | ARG2, + /* D3DTOP_MODULATEINVALPHA_ADDCOLOR */ ARG1 | ARG2, + /* D3DTOP_MODULATEINVCOLOR_ADDALPHA */ ARG1 | ARG2, + /* D3DTOP_BUMPENVMAP */ ARG1 | ARG2, + /* D3DTOP_BUMPENVMAPLUMINANCE */ ARG1 | ARG2, + /* D3DTOP_DOTPRODUCT3 */ ARG1 | ARG2, + /* D3DTOP_MULTIPLYADD */ ARG1 | ARG2 | ARG0, + /* D3DTOP_LERP */ ARG1 | ARG2 | ARG0 + }; + unsigned int i; + DWORD ttff; + DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; + + for(i = 0; i < GL_LIMITS(texture_stages); i++) { + IWineD3DBaseTextureImpl *texture; + settings->op[i].padding = 0; + if(stateblock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) { + settings->op[i].cop = WINED3DTOP_DISABLE; + settings->op[i].aop = WINED3DTOP_DISABLE; + settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED; + settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED; + settings->op[i].color_correction = WINED3DFMT_UNKNOWN; + settings->op[i].dst = resultreg; + settings->op[i].tex_type = tex_1d; + settings->op[i].projected = proj_none; + i++; + break; + } + + texture = (IWineD3DBaseTextureImpl *) stateblock->textures[i]; + if(texture) { + settings->op[i].color_correction = texture->baseTexture.shader_conversion_group; + if(ignore_textype) { + settings->op[i].tex_type = tex_1d; + } else { + switch(stateblock->textureDimensions[i]) { + case GL_TEXTURE_1D: + settings->op[i].tex_type = tex_1d; + break; + case GL_TEXTURE_2D: + settings->op[i].tex_type = tex_2d; + break; + case GL_TEXTURE_3D: + settings->op[i].tex_type = tex_3d; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + settings->op[i].tex_type = tex_cube; + break; + case GL_TEXTURE_RECTANGLE_ARB: + settings->op[i].tex_type = tex_rect; + break; + } + } + } else { + settings->op[i].color_correction = WINED3DFMT_UNKNOWN; + settings->op[i].tex_type = tex_1d; + } + + cop = stateblock->textureState[i][WINED3DTSS_COLOROP]; + aop = stateblock->textureState[i][WINED3DTSS_ALPHAOP]; + + carg1 = (args[cop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_COLORARG1] : 0xffffffff; + carg2 = (args[cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : 0xffffffff; + carg0 = (args[cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : 0xffffffff; + + if(is_invalid_op(stateblock->wineD3DDevice, i, cop, + carg1, carg2, carg0)) { + carg0 = 0xffffffff; + carg2 = 0xffffffff; + carg1 = WINED3DTA_CURRENT; + cop = WINED3DTOP_SELECTARG1; + } + + if(cop == WINED3DTOP_DOTPRODUCT3) { + /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates + * the color result to the alpha component of the destination + */ + aop = cop; + aarg1 = carg1; + aarg2 = carg2; + aarg0 = carg0; + } else { + aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff; + aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff; + aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff; + } + + if(i == 0 && stateblock->textures[0] && + stateblock->renderState[WINED3DRS_COLORKEYENABLE] && + (stateblock->textureDimensions[0] == GL_TEXTURE_2D || + stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { + IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + + if(surf->CKeyFlags & WINEDDSD_CKSRCBLT && + getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) { + + if(aop == WINED3DTOP_DISABLE) { + aarg1 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_SELECTARG1; + } + else if(aop == WINED3DTOP_SELECTARG1 && aarg1 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + aarg2 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_MODULATE; + } + else aarg1 = WINED3DTA_TEXTURE; + } + else if(aop == WINED3DTOP_SELECTARG2 && aarg2 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + aarg1 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_MODULATE; + } + else aarg2 = WINED3DTA_TEXTURE; + } + } + } + + if(is_invalid_op(stateblock->wineD3DDevice, i, aop, + aarg1, aarg2, aarg0)) { + aarg0 = 0xffffffff; + aarg2 = 0xffffffff; + aarg1 = WINED3DTA_CURRENT; + aop = WINED3DTOP_SELECTARG1; + } + + if(carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE || + aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE) { + ttff = stateblock->textureState[i][WINED3DTSS_TEXTURETRANSFORMFLAGS]; + if(ttff == (WINED3DTTFF_PROJECTED | WINED3DTTFF_COUNT3)) { + settings->op[i].projected = proj_count3; + } else if(ttff == (WINED3DTTFF_PROJECTED | WINED3DTTFF_COUNT4)) { + settings->op[i].projected = proj_count4; + } else { + settings->op[i].projected = proj_none; + } + } else { + settings->op[i].projected = proj_none; + } + + settings->op[i].cop = cop; + settings->op[i].aop = aop; + settings->op[i].carg0 = carg0; + settings->op[i].carg1 = carg1; + settings->op[i].carg2 = carg2; + settings->op[i].aarg0 = aarg0; + settings->op[i].aarg1 = aarg1; + settings->op[i].aarg2 = aarg2; + + if(stateblock->textureState[i][WINED3DTSS_RESULTARG] == WINED3DTA_TEMP) { + settings->op[i].dst = tempreg; + } else { + settings->op[i].dst = resultreg; + } + } + + /* Clear unsupported stages */ + for(; i < MAX_TEXTURES; i++) { + memset(&settings->op[i], 0xff, sizeof(settings->op[i])); + } + + if(stateblock->renderState[WINED3DRS_FOGENABLE] == FALSE) { + settings->fog = FOG_OFF; + } else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { + switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) { + case WINED3DFOG_NONE: + case WINED3DFOG_LINEAR: + settings->fog = FOG_LINEAR; + break; + case WINED3DFOG_EXP: + settings->fog = FOG_EXP; + break; + case WINED3DFOG_EXP2: + settings->fog = FOG_EXP2; + break; + } + } else { + switch(stateblock->renderState[WINED3DRS_FOGTABLEMODE]) { + case WINED3DFOG_LINEAR: + settings->fog = FOG_LINEAR; + break; + case WINED3DFOG_EXP: + settings->fog = FOG_EXP; + break; + case WINED3DFOG_EXP2: + settings->fog = FOG_EXP2; + break; + } + } + if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + settings->sRGB_write = 1; + } else { + settings->sRGB_write = 0; + } +} +#undef GLINFO_LOCATION + +struct ffp_desc *find_ffp_shader(struct hash_table_t *fragment_shaders, struct ffp_settings *settings) +{ + return (struct ffp_desc *)hash_table_get(fragment_shaders, settings);} + +void add_ffp_shader(struct hash_table_t *shaders, struct ffp_desc *desc) { + struct ffp_settings *key = HeapAlloc(GetProcessHeap(), 0, sizeof(*key)); + /* Note that the key is the implementation independent part of the ffp_desc structure, + * whereas desc points to an extended structure with implementation specific parts. + * Make a copy of the key because hash_table_put takes ownership of it + */ + *key = desc->settings; + hash_table_put(shaders, key, desc); +} + +/* Activates the texture dimension according to the bound D3D texture. + * Does not care for the colorop or correct gl texture unit(when using nvrc) + * Requires the caller to activate the correct unit before + */ +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(stateblock->textures[stage]) { + switch(stateblock->textureDimensions[stage]) { + case GL_TEXTURE_2D: + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + glEnable(GL_TEXTURE_2D); + checkGLcall("glEnable(GL_TEXTURE_2D)"); + break; + case GL_TEXTURE_RECTANGLE_ARB: + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + glEnable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)"); + break; + case GL_TEXTURE_3D: + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + glEnable(GL_TEXTURE_3D); + checkGLcall("glEnable(GL_TEXTURE_3D)"); + break; + case GL_TEXTURE_CUBE_MAP_ARB: + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + glEnable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)"); + break; + } + } else { + glEnable(GL_TEXTURE_2D); + checkGLcall("glEnable(GL_TEXTURE_2D)"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + /* Binding textures is done by samplers. A dummy texture will be bound */ + } +} + +void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD sampler = state - STATE_SAMPLER(0); + DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler]; + + /* No need to enable / disable anything here for unused samplers. The tex_colorop + * handler takes care. Also no action is needed with pixel shaders, or if tex_colorop + * will take care of this business + */ + if(mapped_stage == -1 || mapped_stage >= GL_LIMITS(textures)) return; + if(sampler >= stateblock->lowest_disabled_stage) return; + if(isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) return; + + texture_activate_dimensions(sampler, stateblock, context); +} +#undef GLINFO_LOCATION + +unsigned int ffp_program_key_hash(void *key) { + struct ffp_settings *k = (struct ffp_settings *)key; + unsigned int hash = 0, i; + DWORD *blob; + + /* This takes the texture op settings of stage 0 and 1 into account. + * how exactly depends on the memory laybout of the compiler, but it + * should not matter too much. Stages > 1 are used rarely, so there's + * no need to process them. Even if they're used it is likely that + * the ffp setup has distinct stage 0 and 1 settings. + */ + for(i = 0; i < 2; i++) { + blob = (DWORD *) &k->op[i]; + hash ^= blob[0] ^ blob[1]; + } + + hash += ~(hash << 15); + hash ^= (hash >> 10); + hash += (hash << 3); + hash ^= (hash >> 6); + hash += ~(hash << 11); + hash ^= (hash >> 16); + + return hash; +} + +BOOL ffp_program_key_compare(void *keya, void *keyb) { + struct ffp_settings *ka = (struct ffp_settings *)keya; + struct ffp_settings *kb = (struct ffp_settings *)keyb; + + return memcmp(ka, kb, sizeof(*ka)) == 0; +} diff --git a/reactos/dll/directx/wine/wined3d/vertexbuffer.c b/reactos/dll/directx/wine/wined3d/vertexbuffer.c index bd599c4f5f2..f458732c9f2 100644 --- a/reactos/dll/directx/wine/wined3d/vertexbuffer.c +++ b/reactos/dll/directx/wine/wined3d/vertexbuffer.c @@ -4,6 +4,7 @@ * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * Copyright 2004 Christian Costa + * Copyright 2007 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -104,76 +105,187 @@ static DWORD WINAPI IWineD3DVertexBufferImpl_GetPriority(IWineD3DVertexBuffer return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface); } -static void fixup_vertices( - BYTE *src, BYTE *dst, - int stride, - int num, - int pos, BOOL haspos, - int diffuse, BOOL hasdiffuse, - int specular, BOOL hasspecular -) { - int i; +static inline void fixup_d3dcolor(DWORD *pos) { + DWORD srcColor = *pos; + + /* Color conversion like in drawStridedSlow. watch out for little endianity + * If we want that stuff to work on big endian machines too we have to consider more things + * + * 0xff000000: Alpha mask + * 0x00ff0000: Blue mask + * 0x0000ff00: Green mask + * 0x000000ff: Red mask + */ + *pos = 0; + *pos |= (srcColor & 0xff00ff00) ; /* Alpha Green */ + *pos |= (srcColor & 0x00ff0000) >> 16; /* Red */ + *pos |= (srcColor & 0x000000ff) << 16; /* Blue */ +} + +static inline void fixup_transformed_pos(float *p) { float x, y, z, w; - for(i = num - 1; i >= 0; i--) { - if(haspos) { - float *p = (float *) ((src + pos) + i * stride); + /* rhw conversion like in drawStridedSlow */ + if(p[3] == 1.0 || ((p[3] < eps) && (p[3] > -eps))) { + x = p[0]; + y = p[1]; + z = p[2]; + w = 1.0; + } else { + w = 1.0 / p[3]; + x = p[0] * w; + y = p[1] * w; + z = p[2] * w; + } + p[0] = x; + p[1] = y; + p[2] = z; + p[3] = w; +} - /* rhw conversion like in drawStridedSlow */ - if(p[3] == 1.0 || ((p[3] < eps) && (p[3] > -eps))) { - x = p[0]; - y = p[1]; - z = p[2]; - w = 1.0; - } else { - w = 1.0 / p[3]; - x = p[0] * w; - y = p[1] * w; - z = p[2] * w; - } - p = (float *) (dst + i * stride + pos); - p[0] = x; - p[1] = y; - p[2] = z; - p[3] = w; - } - if(hasdiffuse) { - DWORD srcColor, *dstColor = (DWORD *) (dst + i * stride + diffuse); - srcColor = * (DWORD *) ( (src + diffuse) + i * stride); +DWORD *find_conversion_shift(IWineD3DVertexBufferImpl *This, WineDirect3DVertexStridedData *strided, DWORD stride) { + DWORD *ret, i, shift, j, type; + DWORD orig_type_size; - /* Color conversion like in drawStridedSlow. watch out for little endianity - * If we want that stuff to work on big endian machines too we have to consider more things - * - * 0xff000000: Alpha mask - * 0x00ff0000: Blue mask - * 0x0000ff00: Green mask - * 0x000000ff: Red mask - */ + if(!stride) { + TRACE("No shift\n"); + return NULL; + } - *dstColor = 0; - *dstColor |= (srcColor & 0xff00ff00) ; /* Alpha Green */ - *dstColor |= (srcColor & 0x00ff0000) >> 16; /* Red */ - *dstColor |= (srcColor & 0x000000ff) << 16; /* Blue */ - } - if(hasspecular) { - DWORD srcColor, *dstColor = (DWORD *) (dst + i * stride + specular); - srcColor = * (DWORD *) ( (src + specular) + i * stride); + This->conv_stride = stride; + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DWORD) * stride); + for(i = 0; i < MAX_ATTRIBS; i++) { + if(strided->u.input[i].VBO != This->vbo) continue; - /* Similar to diffuse - * TODO: Write the alpha value out for fog coords + type = strided->u.input[i].dwType; + if(type == WINED3DDECLTYPE_FLOAT16_2) { + shift = 4; + } else if(type == WINED3DDECLTYPE_FLOAT16_4) { + shift = 8; + /* Pre-shift the last 4 bytes in the FLOAT16_4 by 4 bytes - this makes FLOAT16_2 and FLOAT16_4 conversions + * compatible */ - *dstColor = 0; - *dstColor |= (srcColor & 0xff00ff00) ; /* Alpha Green */ - *dstColor |= (srcColor & 0x00ff0000) >> 16; /* Red */ - *dstColor |= (srcColor & 0x000000ff) << 16; /* Blue */ + for(j = 4; j < 8; j++) { + ret[(DWORD_PTR) strided->u.input[i].lpData + j ] += 4; + } + } else { + shift = 0; + } + This->conv_stride += shift; + + if(shift) { + orig_type_size = WINED3D_ATR_TYPESIZE(type) * WINED3D_ATR_SIZE(type); + for(j = (DWORD_PTR) strided->u.input[i].lpData + orig_type_size; j < stride; j++) { + ret[j] += shift; + } } } + + if(TRACE_ON(d3d)) { + TRACE("Dumping conversion shift:\n"); + for(i = 0; i < stride; i++) { + TRACE("[%d]", ret[i]); + } + TRACE("\n"); + } + return ret; +} + +static inline BOOL process_converted_attribute(IWineD3DVertexBufferImpl *This, + const enum vbo_conversion_type conv_type, + const WineDirect3DStridedData *attrib, + DWORD *stride_this_run, const DWORD type) { + DWORD attrib_size; + BOOL ret = FALSE; + int i; + DWORD offset = This->resource.wineD3DDevice->stateBlock->streamOffset[attrib->streamNo]; + DWORD_PTR data; + + /* Check for some valid situations which cause us pain. One is if the buffer is used for + * constant attributes(stride = 0), the other one is if the buffer is used on two streams + * with different strides. In the 2nd case we might have to drop conversion entirely, + * it is possible that the same bytes are once read as FLOAT2 and once as UBYTE4N. + */ + if(attrib->dwStride == 0) { + FIXME("%s used with stride 0, let's hope we get the vertex stride from somewhere else\n", + debug_d3ddecltype(type)); + } else if(attrib->dwStride != *stride_this_run && + *stride_this_run) { + FIXME("Got two concurrent strides, %d and %d\n", attrib->dwStride, *stride_this_run); + } else { + *stride_this_run = attrib->dwStride; + if(This->stride != *stride_this_run) { + /* We rely that this happens only on the first converted attribute that is found, + * if at all. See above check + */ + TRACE("Reconverting because converted attributes occur, and the stride changed\n"); + This->stride = *stride_this_run; + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This->conv_map); + This->conv_map = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->conv_map) * This->stride); + ret = TRUE; + } + } + + data = (((DWORD_PTR) attrib->lpData) + offset) % This->stride; + attrib_size = WINED3D_ATR_SIZE(type) * WINED3D_ATR_TYPESIZE(type); + for(i = 0; i < attrib_size; i++) { + if(This->conv_map[data + i] != conv_type) { + TRACE("Byte %ld in vertex changed\n", i + data); + TRACE("It was type %d, is %d now\n", This->conv_map[data + i], conv_type); + ret = TRUE; + This->conv_map[data + i] = conv_type; + } + } + return ret; +} + +static inline BOOL check_attribute(IWineD3DVertexBufferImpl *This, const WineDirect3DStridedData *attrib, + const BOOL check_d3dcolor, const BOOL is_ffp_position, const BOOL is_ffp_color, + DWORD *stride_this_run, BOOL *float16_used) { + BOOL ret = FALSE; + DWORD type; + + /* Ignore attributes that do not have our vbo. After that check we can be sure that the attribute is + * there, on nonexistent attribs the vbo is 0. + */ + if(attrib->VBO != This->vbo) return FALSE; + + type = attrib->dwType; + /* Look for newly appeared conversion */ + if(!GL_SUPPORT(NV_HALF_FLOAT) && ( + type == WINED3DDECLTYPE_FLOAT16_2 || + type == WINED3DDECLTYPE_FLOAT16_4)) { + + ret = process_converted_attribute(This, CONV_FLOAT16_2, attrib, stride_this_run, type); + + if(is_ffp_position) { + FIXME("Test FLOAT16 fixed function processing positions\n"); + } else if(is_ffp_color) { + FIXME("test FLOAT16 fixed function processing colors\n"); + } + *float16_used = TRUE; + } else if(check_d3dcolor && type == WINED3DDECLTYPE_D3DCOLOR) { + + ret = process_converted_attribute(This, CONV_D3DCOLOR, attrib, stride_this_run, WINED3DDECLTYPE_D3DCOLOR); + + if(!is_ffp_color) { + FIXME("Test for non-color fixed function D3DCOLOR type\n"); + } + } else if(is_ffp_position && type == WINED3DDECLTYPE_FLOAT4) { + ret = process_converted_attribute(This, CONV_POSITIONT, attrib, stride_this_run, WINED3DDECLTYPE_FLOAT4); + } else if(This->conv_map) { + ret = process_converted_attribute(This, CONV_NONE, attrib, stride_this_run, type); + } + return ret; } inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *This) { - WineDirect3DVertexStridedData strided; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + BOOL ret = FALSE; + int i; + DWORD stride_this_run = 0; + BOOL float16_used = FALSE; /* In d3d7 the vertex buffer declaration NEVER changes because it is stored in the d3d7 vertex buffer. * Once we have our declaration there is no need to look it up again. @@ -182,92 +294,220 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T return FALSE; } - /* There are certain vertex data types that need to be fixed up. The Vertex Buffers FVF doesn't - * help finding them, only the vertex declaration or the device FVF can determine that at drawPrim - * time. Rules are as follows: + TRACE("Finding vertex buffer conversion information\n"); + /* Certain declaration types need some fixups before we can pass them to opengl. This means D3DCOLOR attributes with fixed + * function vertex processing, FLOAT4 POSITIONT with fixed function, and FLOAT16 if GL_NV_half_float is not supported. * - * -> No modification when Vertex Shaders are used - * -> Fix up position1 and position 2 if they are XYZRHW - * -> Fix up diffuse color - * -> Fix up specular color + * The vertex buffer FVF doesn't help with finding them, we have to use the decoded vertex declaration and pick the things + * that concern the current buffer. A problem with this is that this can change between draws, so we have to validate + * the information and reprocess the buffer if it changes, and avoid false positives for performance reasons. * - * The Declaration is only known at drawing time, and it can change from draw to draw. If any converted values - * are changed, the whole buffer has to be reconverted and reloaded. (Converting is SLOW, so if this happens too - * often PreLoad stops converting entirely and falls back to drawStridedSlow). + * We have to distinguish between vertex shaders and fixed function to pick the way we access the + * strided vertex information. * - * Reconvert if: - * -> New semantics that have to be converted appear - * -> The position of semantics that have to be converted changes - * -> The stride of the vertex changed AND there is stuff that needs conversion - * -> (If a vertex shader is bound and in use assume that nothing that needs conversion is there) + * This code sets up a per-byte array with the size of the detected stride of the arrays in the + * buffer. For each byte we have a field that marks the conversion needed on this byte. For example, + * the following declaration with fixed function vertex processing: * - * Return values: - * TRUE: Reload is needed - * FALSE: otherwise + * POSITIONT, FLOAT4 + * NORMAL, FLOAT3 + * DIFFUSE, FLOAT16_4 + * SPECULAR, D3DCOLOR + * + * Will result in + * { POSITIONT }{ NORMAL }{ DIFFUSE }{SPECULAR } + * [P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][0][0][0][0][0][0][0][0][0][0][0][0][F][F][F][F][F][F][F][F][C][C][C][C] + * + * Where in this example map P means 4 component position conversion, 0 means no conversion, F means FLOAT16_2 conversion + * and C means D3DCOLOR conversion(red / blue swizzle). + * + * If we're doing conversion and the stride changes we have to reconvert the whole buffer. Note that we do not mind if the + * semantic changes, we only care for the conversion type. So if the NORMAL is replaced with a TEXCOORD, nothing has to be + * done, or if the DIFFUSE is replaced with a D3DCOLOR BLENDWEIGHT we can happily dismiss the change. Some conversion types + * depend on the semantic as well, for example a FLOAT4 texcoord needs no conversion while a FLOAT4 positiont needs one */ + if(use_vs(device)) { + TRACE("vhsader\n"); + /* If the current vertex declaration is marked for no half float conversion don't bother to + * analyse the strided streams in depth, just set them up for no conversion. Return decl changed + * if we used conversion before + */ + if(!((IWineD3DVertexDeclarationImpl *) device->stateBlock->vertexDecl)->half_float_conv_needed) { + if(This->conv_map) { + TRACE("Now using shaders without conversion, but conversion used before\n"); + HeapFree(GetProcessHeap(), 0, This->conv_map); + HeapFree(GetProcessHeap(), 0, This->conv_shift); + This->conv_map = NULL; + This->stride = 0; + This->conv_shift = NULL; + This->conv_stride = 0; + return TRUE; + } else { + return FALSE; + } + } + for(i = 0; i < MAX_ATTRIBS; i++) { + ret = check_attribute(This, &device->strided_streams.u.input[i], FALSE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + } - if (use_vs(device)) { - /* Assume no conversion */ - memset(&strided, 0, sizeof(strided)); + /* Recalculate the conversion shift map if the declaration has changed, + * and we're using float16 conversion or used it on the last run + */ + if(ret && (float16_used || This->conv_map)) { + HeapFree(GetProcessHeap(), 0, This->conv_shift); + This->conv_shift = find_conversion_shift(This, &device->strided_streams, This->stride); + } } else { - /* we need a copy because we modify some params */ - memcpy(&strided, &device->strided_streams, sizeof(strided)); + /* Fixed function is a bit trickier. We have to take care for D3DCOLOR types, FLOAT4 positions and of course + * FLOAT16s if not supported. Also, we can't iterate over the array, so use macros to generate code for all + * the attributes that our current fixed function pipeline implementation cares for. + */ + ret = check_attribute(This, &device->strided_streams.u.s.position, TRUE, TRUE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.normal, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.diffuse, TRUE, FALSE, TRUE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.specular, TRUE, FALSE, TRUE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[0], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[1], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[2], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[3], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[4], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[5], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[6], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = check_attribute(This, &device->strided_streams.u.s.texCoords[7], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - /* Filter out data that does not come from this VBO */ - if(strided.u.s.position.VBO != This->vbo) memset(&strided.u.s.position, 0, sizeof(strided.u.s.position)); - if(strided.u.s.diffuse.VBO != This->vbo) memset(&strided.u.s.diffuse, 0, sizeof(strided.u.s.diffuse)); - if(strided.u.s.specular.VBO != This->vbo) memset(&strided.u.s.specular, 0, sizeof(strided.u.s.specular)); - if(strided.u.s.position2.VBO != This->vbo) memset(&strided.u.s.position2, 0, sizeof(strided.u.s.position2)); + if(float16_used) FIXME("Float16 conversion used with fixed function vertex processing\n"); } - /* We have a declaration now in the buffer */ + if(stride_this_run == 0 && This->conv_map) { + /* Sanity test */ + if(ret == FALSE) { + ERR("no converted attributes found, old conversion map exists, and no declaration change???\n"); + } + HeapFree(GetProcessHeap(), 0, This->conv_map); + This->conv_map = NULL; + This->stride = 0; + } This->Flags |= VBFLAG_HASDESC; - /* Find out if reload is needed - * Position of the semantic in the vertex and the stride must be equal to the stored type. Don't mind if only unconverted stuff changed. - * - * If some stuff does not exist in the buffer, then lpData, dwStride and dwType are memsetted to 0. So if the semantic didn't exist before - * and does not exist now all 3 values will be equal(=0). - * - * Checking the lpData field alone is not enough, because data may appear at offset 0 in the buffer. This is the same location as nonexistent - * data uses, so we have to check the type and stride too. Colors can be at offset 0 too, because it is perfectly fine to render from 2 or more - * buffers at the same time and get the position from one and the color from the other buffer. - */ - if( /* Position transformed vs untransformed */ - ((This->strided.u.s.position_transformed || strided.u.s.position_transformed) && - (This->strided.u.s.position.lpData != strided.u.s.position.lpData || - This->strided.u.s.position.dwType != strided.u.s.position.dwType)) || - /* Diffuse position and data type */ - This->strided.u.s.diffuse.lpData != strided.u.s.diffuse.lpData || This->strided.u.s.diffuse.dwStride != strided.u.s.diffuse.dwStride || - This->strided.u.s.diffuse.dwType != strided.u.s.diffuse.dwType || - /* Specular position and data type */ - This->strided.u.s.specular.lpData != strided.u.s.specular.lpData || This->strided.u.s.specular.dwStride != strided.u.s.specular.dwStride || - This->strided.u.s.specular.dwType != strided.u.s.specular.dwType) { + if(ret) TRACE("Conversion information changed\n"); + return ret; +} - TRACE("Declaration changed, reloading buffer\n"); - /* Set the new description */ - memcpy(&This->strided, &strided, sizeof(strided)); - return TRUE; +static void check_vbo_size(IWineD3DVertexBufferImpl *This) { + DWORD size = This->conv_stride ? This->conv_stride * (This->resource.size / This->stride) : This->resource.size; + if(This->vbo_size != size) { + TRACE("Old size %d, creating new size %d\n", This->vbo_size, size); + ENTER_GL(); + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); + checkGLcall("glBindBufferARB"); + GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, This->vbo_usage)); + This->vbo_size = size; + checkGLcall("glBufferDataARB"); + LEAVE_GL(); + } +} + +static void CreateVBO(IWineD3DVertexBufferImpl *This) { + GLenum error, glUsage; + DWORD vboUsage = This->resource.usage; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", This, debug_d3dusage(vboUsage)); + + /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */ + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + + /* Make sure that the gl error is cleared. Do not use checkGLcall + * here because checkGLcall just prints a fixme and continues. However, + * if an error during VBO creation occurs we can fall back to non-vbo operation + * with full functionality(but performance loss) + */ + while(glGetError() != GL_NO_ERROR); + + /* Basically the FVF parameter passed to CreateVertexBuffer is no good + * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with + * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer + * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified + * to check if the rhw and color values are in the correct format. + */ + + GL_EXTCALL(glGenBuffersARB(1, &This->vbo)); + error = glGetError(); + if(This->vbo == 0 || error != GL_NO_ERROR) { + WARN("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error); + goto error; } - return FALSE; + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); + error = glGetError(); + if(error != GL_NO_ERROR) { + WARN("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error); + goto error; + } + + /* Don't use static, because dx apps tend to update the buffer + * quite often even if they specify 0 usage. Because we always keep the local copy + * we never read from the vbo and can create a write only opengl buffer. + */ + switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) { + case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC: + case WINED3DUSAGE_DYNAMIC: + TRACE("Gl usage = GL_STREAM_DRAW\n"); + glUsage = GL_STREAM_DRAW_ARB; + break; + case WINED3DUSAGE_WRITEONLY: + default: + TRACE("Gl usage = GL_DYNAMIC_DRAW\n"); + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + } + + /* Reserve memory for the buffer. The amount of data won't change + * so we are safe with calling glBufferData once with a NULL ptr and + * calling glBufferSubData on updates + */ + GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, This->resource.size, NULL, glUsage)); + error = glGetError(); + if(error != GL_NO_ERROR) { + WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); + goto error; + } + This->vbo_size = This->resource.size; + This->vbo_usage = glUsage; + This->dirtystart = 0; + This->dirtyend = This->resource.size; + This->Flags |= VBFLAG_DIRTY; + + LEAVE_GL(); + + return; + error: + /* Clean up all vbo init, but continue because we can work without a vbo :-) */ + FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n"); + if(This->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); + This->vbo = 0; + LEAVE_GL(); + return; } static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *iface) { IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; BYTE *data; - UINT start = 0, end = 0, stride = 0; + UINT start = 0, end = 0, vertices; BOOL declChanged = FALSE; + int i, j; TRACE("(%p)->()\n", This); - if(This->Flags & VBFLAG_LOAD) { - return; /* Already doing that stuff */ - } - if(!This->vbo) { /* TODO: Make converting independent from VBOs */ - return; /* Not doing any conversion */ + if(This->Flags & VBFLAG_CREATEVBO) { + CreateVBO(This); + This->Flags &= ~VBFLAG_CREATEVBO; + } else { + return; /* Not doing any conversion */ + } } /* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */ @@ -275,7 +515,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if declChanged = IWineD3DVertexBufferImpl_FindDecl(This); } else if(This->Flags & VBFLAG_HASDESC) { /* Reuse the declaration stored in the buffer. It will most likely not change, and if it does - * the stream source state handler will call PreLoad again and the change will be cought + * the stream source state handler will call PreLoad again and the change will be caught */ } else { /* Cannot get a declaration, and no declaration is stored in the buffer. It is pointless to preload @@ -286,21 +526,22 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if } /* If applications change the declaration over and over, reconverting all the time is a huge - * performance hit. So count the declaration changes and release the VBO if there are too much - * of them(and thus stop converting) + * performance hit. So count the declaration changes and release the VBO if there are too many + * of them (and thus stop converting) */ if(declChanged) { This->declChanges++; This->draws = 0; if(This->declChanges > VB_MAXDECLCHANGES) { - FIXME("Too much declaration changes, stopping converting\n"); + FIXME("Too many declaration changes, stopping converting\n"); ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); This->vbo = 0; + HeapFree(GetProcessHeap(), 0, This->conv_shift); /* The stream source state handler might have read the memory of the vertex buffer already * and got the memory in the vbo which is not valid any longer. Dirtify the stream source @@ -311,6 +552,7 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if return; } + check_vbo_size(This); } else { /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without @@ -327,6 +569,11 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if end = This->resource.size; } else if(This->Flags & VBFLAG_DIRTY) { /* No decl change, but dirty data, reload the changed stuff */ + if(This->conv_shift) { + if(This->dirtystart != 0 || This->dirtyend != 0) { + FIXME("Implement partial buffer loading with shifted conversion\n"); + } + } start = This->dirtystart; end = This->dirtyend; } else { @@ -339,15 +586,12 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if This->dirtystart = 0; This->dirtyend = 0; - if (This->strided.u.s.position.dwStride) stride = This->strided.u.s.position.dwStride; - else if(This->strided.u.s.specular.dwStride) stride = This->strided.u.s.specular.dwStride; - else if(This->strided.u.s.diffuse.dwStride) stride = This->strided.u.s.diffuse.dwStride; - else { + if(!This->conv_map) { /* That means that there is nothing to fixup. Just upload from This->resource.allocatedMemory * directly into the vbo. Do not free the system memory copy because drawPrimitive may need it if * the stride is 0, for instancing emulation, vertex blending emulation or shader emulation. */ - TRACE("No conversion needed, locking directly into the VBO in future\n"); + TRACE("No conversion needed\n"); if(!device->isInDraw) { ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); @@ -361,40 +605,103 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if return; } - /* OK, we have the original data from the app, the description of the buffer and the dirty area. - * so convert the stuff - */ - data = HeapAlloc(GetProcessHeap(), 0, end-start); - if(!data) { - ERR("Out of memory\n"); - return; - } - memcpy(data, This->resource.allocatedMemory + start, end - start); + /* Now for each vertex in the buffer that needs conversion */ + vertices = This->resource.size / This->stride; - fixup_vertices(data, data, stride, ( end - start) / stride, - /* Position */ - (int)This->strided.u.s.position.lpData, /* Data location */ - This->strided.u.s.position_transformed, /* Do convert? */ - /* Diffuse color */ - (int)This->strided.u.s.diffuse.lpData, /* Location */ - This->strided.u.s.diffuse.dwType == WINED3DDECLTYPE_SHORT4 || This->strided.u.s.diffuse.dwType == WINED3DDECLTYPE_D3DCOLOR, /* Convert? */ - /* specular color */ - (int)This->strided.u.s.specular.lpData, /* location */ - This->strided.u.s.specular.dwType == WINED3DDECLTYPE_SHORT4 || This->strided.u.s.specular.dwType == WINED3DDECLTYPE_D3DCOLOR); + if(This->conv_shift) { + TRACE("Shifted conversion\n"); + data = HeapAlloc(GetProcessHeap(), 0, vertices * This->conv_stride); - if(!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + for(i = start / This->stride; i < min((end / This->stride) + 1, vertices); i++) { + for(j = 0; j < This->stride; j++) { + switch(This->conv_map[j]) { + case CONV_NONE: + data[This->conv_stride * i + j + This->conv_shift[j]] = This->resource.allocatedMemory[This->stride * i + j]; + break; + + case CONV_FLOAT16_2: + { + float *out = (float *) (&data[This->conv_stride * i + j + This->conv_shift[j]]); + WORD *in = (WORD *) (&This->resource.allocatedMemory[i * This->stride + j]); + + out[1] = float_16_to_32(in + 1); + out[0] = float_16_to_32(in + 0); + j += 3; /* Skip 3 additional bytes,as a FLOAT16_2 has 4 bytes */ + break; + } + + default: + FIXME("Unimplemented conversion %d in shifted conversion\n", This->conv_map[j]); + } + } + } + + ENTER_GL(); + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); + checkGLcall("glBindBufferARB"); + GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, vertices * This->conv_stride, data)); + checkGLcall("glBufferSubDataARB"); + LEAVE_GL(); + + } else { + data = HeapAlloc(GetProcessHeap(), 0, This->resource.size); + memcpy(data + start, This->resource.allocatedMemory + start, end - start); + for(i = start / This->stride; i < min((end / This->stride) + 1, vertices); i++) { + for(j = 0; j < This->stride; j++) { + switch(This->conv_map[j]) { + case CONV_NONE: + /* Done already */ + j += 3; + break; + case CONV_D3DCOLOR: + fixup_d3dcolor((DWORD *) (data + i * This->stride + j)); + j += 3; + break; + + case CONV_POSITIONT: + fixup_transformed_pos((float *) (data + i * This->stride + j)); + j += 15; + break; + + case CONV_FLOAT16_2: + ERR("Did not expect FLOAT16 conversion in unshifted conversion\n"); + default: + FIXME("Unimplemented conversion %d in shifted conversion\n", This->conv_map[j]); + } + } + } + + ENTER_GL(); + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); + checkGLcall("glBindBufferARB"); + GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end - start, data + start)); + checkGLcall("glBufferSubDataARB"); + LEAVE_GL(); } - ENTER_GL(); - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); - checkGLcall("glBindBufferARB"); - GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start, end - start, data)); - checkGLcall("glBufferSubDataARB"); - LEAVE_GL(); HeapFree(GetProcessHeap(), 0, data); } +static void WINAPI IWineD3DVertexBufferImpl_UnLoad(IWineD3DVertexBuffer *iface) { + IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + TRACE("(%p)\n", This); + + /* This is easy: The whole content is shadowed in This->resource.allocatedMemory, + * so we only have to destroy the vbo. Only do it if we have a vbo, which implies + * that vbos are supported + */ + if(This->vbo) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); + checkGLcall("glDeleteBuffersARB"); + LEAVE_GL(); + This->vbo = 0; + This->Flags |= VBFLAG_CREATEVBO; /* Recreate the VBO next load */ + } +} + static WINED3DRESOURCETYPE WINAPI IWineD3DVertexBufferImpl_GetType(IWineD3DVertexBuffer *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -481,6 +788,7 @@ const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl = IWineD3DVertexBufferImpl_SetPriority, IWineD3DVertexBufferImpl_GetPriority, IWineD3DVertexBufferImpl_PreLoad, + IWineD3DVertexBufferImpl_UnLoad, IWineD3DVertexBufferImpl_GetType, /* IWineD3DVertexBuffer */ IWineD3DVertexBufferImpl_Lock, @@ -493,6 +801,14 @@ BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWO *vbo = This->vbo; if(This->vbo == 0) { + if(This->Flags & VBFLAG_CREATEVBO) { + CreateVBO(This); + This->Flags &= ~VBFLAG_CREATEVBO; + if(This->vbo) { + *vbo = This->vbo; + return (BYTE *) iOffset; + } + } return This->resource.allocatedMemory + iOffset; } else { return (BYTE *) iOffset; diff --git a/reactos/dll/directx/wine/wined3d/vertexdeclaration.c b/reactos/dll/directx/wine/wined3d/vertexdeclaration.c index 924db6a1c4f..936ef57fbbe 100644 --- a/reactos/dll/directx/wine/wined3d/vertexdeclaration.c +++ b/reactos/dll/directx/wine/wined3d/vertexdeclaration.c @@ -26,6 +26,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl); +#define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info + static void dump_wined3dvertexelement(const WINED3DVERTEXELEMENT *element) { TRACE(" Stream: %d\n", element->Stream); TRACE(" Offset: %d\n", element->Offset); @@ -101,7 +103,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDecl } static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration *iface, - WINED3DVERTEXELEMENT *elements, size_t *element_count) { + WINED3DVERTEXELEMENT *elements, UINT *element_count) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; HRESULT hr = WINED3D_OK; @@ -117,7 +119,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVerte } static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVertexDeclaration *iface, - const WINED3DVERTEXELEMENT *elements, size_t element_count) { + const WINED3DVERTEXELEMENT *elements, UINT element_count) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; HRESULT hr = WINED3D_OK; int i, j; @@ -157,6 +159,18 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte */ if(This->pDeclarationWine[i].Stream >= MAX_STREAMS) continue; + if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_UNUSED) { + WARN("The application tries to use WINED3DDECLTYPE_UNUSED, returning E_FAIL\n"); + /* The caller will release the vdecl, which will free This->pDeclarationWine */ + return E_FAIL; + } + + if(This->pDeclarationWine[i].Offset & 0x3) { + WARN("Declaration element %d is not 4 byte aligned(%d), returning E_FAIL\n", i, This->pDeclarationWine[i].Offset); + HeapFree(GetProcessHeap(), 0, This->pDeclarationWine); + return E_FAIL; + } + if(!isPreLoaded[This->pDeclarationWine[i].Stream]) { This->streams[This->num_streams] = This->pDeclarationWine[i].Stream; This->num_streams++; @@ -175,7 +189,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte (This->swizzled_attribs[j].usage == This->pDeclarationWine[i].Usage && This->swizzled_attribs[j].idx > This->pDeclarationWine[i].UsageIndex)) { memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j], - sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j - 1))); + sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1))); break; } } @@ -183,6 +197,11 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte This->swizzled_attribs[j].usage = This->pDeclarationWine[i].Usage; This->swizzled_attribs[j].idx = This->pDeclarationWine[i].UsageIndex; This->num_swizzled_attribs++; + } else if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2 || + This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4) { + if(!GL_SUPPORT(NV_HALF_FLOAT)) { + This->half_float_conv_needed = TRUE; + } } } diff --git a/reactos/dll/directx/wine/wined3d/vertexshader.c b/reactos/dll/directx/wine/wined3d/vertexshader.c index bd4c2c11aa0..928b97dde3c 100644 --- a/reactos/dll/directx/wine/wined3d/vertexshader.c +++ b/reactos/dll/directx/wine/wined3d/vertexshader.c @@ -6,6 +6,7 @@ * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber * Copyright 2006 Ivan Gyurdiev + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,50 +34,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info -/* Shader debugging - Change the following line to enable debugging of software - vertex shaders */ -#if 0 /* Musxt not be 1 in cvs version */ -# define VSTRACE(A) TRACE A -# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w) -#else -# define VSTRACE(A) -# define TRACE_VSVECTOR(name) -#endif - -/** - * DirectX9 SDK download - * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp - * - * Exploring D3DX - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp - * - * Using Vertex Shaders - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp - * - * Dx9 New - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp - * - * Dx9 Shaders - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp - * - * Dx9 D3DX - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp - * - * FVF - * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp - * - * NVIDIA: DX8 Vertex Shader to NV Vertex Program - * http://developer.nvidia.com/view.asp?IO=vstovp - * - * NVIDIA: Memory Management with VAR - * http://developer.nvidia.com/view.asp?IO=var_memory_management - */ - -/* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders -because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */ +/* TODO: Vertex and Pixel shaders are almost identical, the only exception being the way that some of the data is looked up or the availability of some of the data i.e. some instructions are only valid for pshaders and some for vshaders +because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't surprise me if the program can be cross compiled using a large body of shared code */ #define GLNAME_REQUIRE_GLSL ((const char *)1) @@ -296,6 +255,9 @@ static inline void find_swizzled_attribs(IWineD3DVertexDeclaration *declaration, for(i = 0; i < decl->num_swizzled_attribs; i++) { for(j = 0; j < MAX_ATTRIBS; j++) { + + if(!This->baseShader.reg_maps.attributes[j]) continue; + usage_token = This->semantics_in[j].usage; usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT; @@ -336,7 +298,7 @@ static inline void find_swizzled_attribs(IWineD3DVertexDeclaration *declaration, oldswizzles[i].usage == This->swizzled_attribs[j].usage && oldswizzles[i].idx > This->swizzled_attribs[j].idx)) { memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j], - sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j - 1))); + sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1))); break; } } @@ -381,122 +343,7 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader( buffer.lineNo = 0; buffer.newline = TRUE; - if (This->baseShader.shader_mode == SHADER_GLSL) { - - /* Create the hw GLSL shader program and assign it as the baseShader.prgId */ - GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); - - /* Base Declarations */ - shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION); - - /* Base Shader Body */ - shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction); - - /* Unpack 3.0 outputs */ - if (This->baseShader.hex_version >= WINED3DVS_VERSION(3,0)) { - shader_addline(&buffer, "order_ps_input(OUT);\n"); - } else { - shader_addline(&buffer, "order_ps_input();\n"); - } - - /* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */ - if (!reg_maps->fog) - shader_addline(&buffer, "gl_FogFragCoord = gl_Position.z;\n"); - - /* Write the final position. - * - * OpenGL coordinates specify the center of the pixel while d3d coords specify - * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains - * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x - * contains 1.0 to allow a mad. - */ - shader_addline(&buffer, "gl_Position.xy = gl_Position.xy * posFixup.xy + posFixup.zw;\n"); - - /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c - * - * Basically we want(in homogenous coordinates) z = z * 2 - 1. However, shaders are run - * before the homogenous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w, - * which is the same as z = z / 2 - w. - */ - shader_addline(&buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); - - shader_addline(&buffer, "}\n"); - - TRACE("Compiling shader object %u\n", shader_obj); - GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL)); - GL_EXTCALL(glCompileShaderARB(shader_obj)); - print_glsl_info_log(&GLINFO_LOCATION, shader_obj); - - /* Store the shader object */ - This->baseShader.prgId = shader_obj; - - } else if (This->baseShader.shader_mode == SHADER_ARB) { - - /* Create the hw ARB shader */ - shader_addline(&buffer, "!!ARBvp1.0\n"); - shader_addline(&buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset); - - /* Mesa supports only 95 constants */ - if (GL_VEND(MESA) || GL_VEND(WINE)) - This->baseShader.limits.constant_float = - min(95, This->baseShader.limits.constant_float); - - /* Some instructions need a temporary register. Add it if needed, but only if it is really needed */ - if(reg_maps->usesnrm || This->rel_offset) { - shader_addline(&buffer, "TEMP TMP;\n"); - } - - /* Base Declarations */ - shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION); - - /* We need a constant to fixup the final position */ - shader_addline(&buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS); - - /* Base Shader Body */ - shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction); - - /* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */ - if (!reg_maps->fog) - shader_addline(&buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); - - /* Write the final position. - * - * OpenGL coordinates specify the center of the pixel while d3d coords specify - * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains - * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x - * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that. - */ - shader_addline(&buffer, "ADD TMP_OUT.x, TMP_OUT.x, posFixup.z;\n"); - shader_addline(&buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, posFixup.w;\n"); - - /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c - * and the glsl equivalent - */ - shader_addline(&buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); - - shader_addline(&buffer, "MOV result.position, TMP_OUT;\n"); - - shader_addline(&buffer, "END\n"); - - /* TODO: change to resource.glObjectHandle or something like that */ - GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId)); - - TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId); - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId)); - - TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId); - /* Create the program and check for errors */ - GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - buffer.bsize, buffer.buffer)); - - if (glGetError() == GL_INVALID_OPERATION) { - GLint errPos; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); - FIXME("HW VertexShader Error at position %d: %s\n", - errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); - This->baseShader.prgId = -1; - } - } + ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_vshader(iface, &buffer); #if 1 /* if were using the data buffer of device then we don't need to free it */ HeapFree(GetProcessHeap(), 0, buffer.buffer); @@ -678,8 +525,12 @@ static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWine DWORD usage_idx; for(i = 0; i < vdecl->declarationWNumElements; i++) { + /* Ignore tesselated streams and the termination entry(position0, stream 255, unused) */ + if(vdecl->pDeclarationWine[i].Stream >= MAX_STREAMS || + vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_UNUSED) continue; + for(j = 0; j < MAX_ATTRIBS; j++) { - if(!This->baseShader.reg_maps.attributes) continue; + if(!This->baseShader.reg_maps.attributes[j]) continue; usage_token = This->semantics_in[j].usage; usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; diff --git a/reactos/dll/directx/wine/wined3d/volume.c b/reactos/dll/directx/wine/wined3d/volume.c index a70a3519eef..36f0495e47e 100644 --- a/reactos/dll/directx/wine/wined3d/volume.c +++ b/reactos/dll/directx/wine/wined3d/volume.c @@ -23,9 +23,47 @@ #include "config.h" #include "wined3d_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info +static void volume_bind_and_dirtify(IWineD3DVolume *iface) { + IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; + IWineD3DVolumeTexture *texture; + int active_sampler; + + /* We don't need a specific texture unit, but after binding the texture the current unit is dirty. + * Read the unit back instead of switching to 0, this avoids messing around with the state manager's + * gl states. The current texture unit should always be a valid one. + * + * To be more specific, this is tricky because we can implicitly be called + * from sampler() in state.c. This means we can't touch anything other than + * whatever happens to be the currently active texture, or we would risk + * marking already applied sampler states dirty again. + * + * TODO: Track the current active texture per GL context instead of using glGet + */ + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + GLint active_texture; + ENTER_GL(); + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); + LEAVE_GL(); + active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB]; + } else { + active_sampler = 0; + } + + if (active_sampler != -1) { + IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler)); + } + + if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DVolumeTexture, (void **)&texture))) { + IWineD3DVolumeTexture_BindTexture(texture); + IWineD3DVolumeTexture_Release(texture); + } else { + ERR("Volume should be part of a volume texture\n"); + } +} + /* ******************************************* IWineD3DVolume IUnknown parts follow ******************************************* */ @@ -97,6 +135,13 @@ static void WINAPI IWineD3DVolumeImpl_PreLoad(IWineD3DVolume *iface) { IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface); } +static void WINAPI IWineD3DVolumeImpl_UnLoad(IWineD3DVolume *iface) { + /* The whole content is shadowed on This->resource.allocatedMemory, and the + * texture name is managed by the VolumeTexture container + */ + TRACE("(%p): Nothing to do\n", iface); +} + static WINED3DRESOURCETYPE WINAPI IWineD3DVolumeImpl_GetType(IWineD3DVolume *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -270,6 +315,8 @@ static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, int TRACE("(%p) : level %u, format %s (0x%08x)\n", This, gl_level, debug_d3dformat(format), format); + volume_bind_and_dirtify(iface); + TRACE("Calling glTexImage3D %x level=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%x, Mem=%p\n", GL_TEXTURE_3D, gl_level, @@ -316,6 +363,7 @@ const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl = IWineD3DVolumeImpl_SetPriority, IWineD3DVolumeImpl_GetPriority, IWineD3DVolumeImpl_PreLoad, + IWineD3DVolumeImpl_UnLoad, IWineD3DVolumeImpl_GetType, /* IWineD3DVolume */ IWineD3DVolumeImpl_GetContainer, diff --git a/reactos/dll/directx/wine/wined3d/volumetexture.c b/reactos/dll/directx/wine/wined3d/volumetexture.c index cf3f33934a0..035cf905f21 100644 --- a/reactos/dll/directx/wine/wined3d/volumetexture.c +++ b/reactos/dll/directx/wine/wined3d/volumetexture.c @@ -23,7 +23,7 @@ #include "config.h" #include "wined3d_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info /* ******************************************* @@ -100,8 +100,6 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac TRACE("(%p) : About to load texture\n", This); - IWineD3DVolumeTexture_BindTexture(iface); - if(!device->isInDraw) { ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); } else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { @@ -135,6 +133,22 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac return ; } +static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface) { + unsigned int i; + IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; + TRACE("(%p)\n", This); + + /* 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++) { + IWineD3DVolume_UnLoad(This->volumes[i]); + } + + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); +} + static WINED3DRESOURCETYPE WINAPI IWineD3DVolumeTextureImpl_GetType(IWineD3DVolumeTexture *iface) { return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface); } @@ -185,18 +199,19 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_BindTexture(IWineD3DVolumeTextur return IWineD3DBaseTextureImpl_BindTexture((IWineD3DBaseTexture *)iface); } -static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnBindTexture(IWineD3DVolumeTexture *iface) { - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - TRACE("(%p) : relay to BaseTexture\n", This); - return IWineD3DBaseTextureImpl_UnBindTexture((IWineD3DBaseTexture *)iface); -} - static UINT WINAPI IWineD3DVolumeTextureImpl_GetTextureDimensions(IWineD3DVolumeTexture *iface) { IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; TRACE("(%p)\n", This); return GL_TEXTURE_3D; } +static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *iface) { + IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; + TRACE("(%p)\n", This); + + return FALSE; +} + static void WINAPI IWineD3DVolumeTextureImpl_ApplyStateChanges(IWineD3DVolumeTexture *iface, const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) { @@ -228,7 +243,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTextu IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; if (Level < This->baseTexture.levels) { TRACE("(%p) Level (%d)\n", This, Level); - return IWineD3DVolume_GetDesc((IWineD3DVolume *) This->volumes[Level], pDesc); + return IWineD3DVolume_GetDesc(This->volumes[Level], pDesc); } else { FIXME("(%p) Level (%d)\n", This, Level); } @@ -237,8 +252,8 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTextu static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTexture *iface, UINT Level, IWineD3DVolume** ppVolumeLevel) { IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; if (Level < This->baseTexture.levels) { - *ppVolumeLevel = (IWineD3DVolume *)This->volumes[Level]; - IWineD3DVolume_AddRef((IWineD3DVolume *) *ppVolumeLevel); + *ppVolumeLevel = This->volumes[Level]; + IWineD3DVolume_AddRef(*ppVolumeLevel); TRACE("(%p) -> level(%d) returning volume@%p\n", This, Level, *ppVolumeLevel); } else { FIXME("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels); @@ -252,7 +267,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_LockBox(IWineD3DVolumeTexture *i IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; if (Level < This->baseTexture.levels) { - hr = IWineD3DVolume_LockBox((IWineD3DVolume *)This->volumes[Level], pLockedVolume, pBox, Flags); + hr = IWineD3DVolume_LockBox(This->volumes[Level], pLockedVolume, pBox, Flags); TRACE("(%p) Level (%d) success(%u)\n", This, Level, hr); } else { @@ -267,7 +282,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnlockBox(IWineD3DVolumeTexture IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; if (Level < This->baseTexture.levels) { - hr = IWineD3DVolume_UnlockBox((IWineD3DVolume*) This->volumes[Level]); + hr = IWineD3DVolume_UnlockBox(This->volumes[Level]); TRACE("(%p) -> level(%d) success(%u)\n", This, Level, hr); } else { @@ -281,7 +296,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTextur IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; This->baseTexture.dirty = TRUE; TRACE("(%p) : dirtyfication of volume Level (0)\n", This); - return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) This->volumes[0], pDirtyBox); + return IWineD3DVolume_AddDirtyBox(This->volumes[0], pDirtyBox); } const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl = @@ -299,6 +314,7 @@ const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl = IWineD3DVolumeTextureImpl_SetPriority, IWineD3DVolumeTextureImpl_GetPriority, IWineD3DVolumeTextureImpl_PreLoad, + IWineD3DVolumeTextureImpl_UnLoad, IWineD3DVolumeTextureImpl_GetType, /* BaseTexture */ IWineD3DVolumeTextureImpl_SetLOD, @@ -311,8 +327,8 @@ const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl = IWineD3DVolumeTextureImpl_GetDirty, /* not in d3d */ IWineD3DVolumeTextureImpl_BindTexture, - IWineD3DVolumeTextureImpl_UnBindTexture, IWineD3DVolumeTextureImpl_GetTextureDimensions, + IWineD3DVolumeTextureImpl_IsCondNP2, IWineD3DVolumeTextureImpl_ApplyStateChanges, /* volume texture */ IWineD3DVolumeTextureImpl_Destroy, diff --git a/reactos/dll/directx/wine/wined3d/wined3d.rbuild b/reactos/dll/directx/wine/wined3d/wined3d.rbuild index f8e3496c308..3f99ec932a7 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d.rbuild +++ b/reactos/dll/directx/wine/wined3d/wined3d.rbuild @@ -19,6 +19,7 @@ uuid msvcrt + ati_fragment_shader.c arb_program_shader.c baseshader.c basetexture.c @@ -30,6 +31,7 @@ drawprim.c glsl_shader.c indexbuffer.c + nvidia_texture_shader.c palette.c pixelshader.c query.c @@ -40,6 +42,8 @@ surface.c surface_gdi.c swapchain.c + swapchain_base.c + swapchain_gdi.c texture.c utils.c vertexbuffer.c diff --git a/reactos/dll/directx/wine/wined3d/wined3d_main.c b/reactos/dll/directx/wine/wined3d/wined3d_main.c index 26e7f707cad..6ae0e809f3c 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_main.c +++ b/reactos/dll/directx/wine/wined3d/wined3d_main.c @@ -4,6 +4,7 @@ * Copyright 2002-2003 The wine-d3d team * Copyright 2002-2003 Raphael Junqueira * Copyright 2004 Jason Edmeades + * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +26,7 @@ #include "initguid.h" #include "wined3d_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(wine_d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d); int num_lock = 0; void (*wine_tsx11_lock_ptr)(void) = NULL; @@ -43,7 +44,8 @@ wined3d_settings_t wined3d_settings = ORM_BACKBUFFER, /* Use the backbuffer to do offscreen rendering */ RTL_AUTO, /* Automatically determine best locking method */ 0, /* The default of memory is set in FillGLCaps */ - NULL /* No wine logo by default */ + NULL, /* No wine logo by default */ + FALSE /* Disable multisampling for now due to Nvidia driver bugs which happens for some users */ }; IWineD3D* WINAPI WineDirect3DCreate(UINT SDKVersion, UINT dxVersion, IUnknown *parent) { @@ -254,6 +256,14 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) wined3d_settings.logo = HeapAlloc(GetProcessHeap(), 0, strlen(buffer) + 1); if(wined3d_settings.logo) strcpy(wined3d_settings.logo, buffer); } + if ( !get_config_key( hkey, appkey, "Multisampling", buffer, size) ) + { + if (!strcmp(buffer,"enabled")) + { + TRACE("Allow multisampling\n"); + wined3d_settings.allow_multisampling = TRUE; + } + } } if (wined3d_settings.vs_mode == VS_HW) TRACE("Allow HW vertex shaders\n"); diff --git a/reactos/dll/directx/wine/wined3d/wined3d_private.h b/reactos/dll/directx/wine/wined3d/wined3d_private.h index d006f876a40..d28161a4658 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private.h @@ -43,39 +43,40 @@ #include "wine/wined3d_gl.h" #include "wine/list.h" -#define ceilf(x) (float)ceil((double)x) /* Hash table functions */ typedef unsigned int (hash_function_t)(void *key); typedef BOOL (compare_function_t)(void *keya, void *keyb); -typedef struct { +#define ceilf(x) (float)ceil((double)x) + +struct hash_table_entry_t { void *key; void *value; unsigned int hash; struct list entry; -} hash_table_entry_t; +}; -typedef struct { +struct hash_table_t { hash_function_t *hash_function; compare_function_t *compare_function; struct list *buckets; unsigned int bucket_count; - hash_table_entry_t *entries; + struct hash_table_entry_t *entries; unsigned int entry_count; struct list free_entries; unsigned int count; unsigned int grow_size; unsigned int shrink_size; -} hash_table_t; +}; -hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function); -void hash_table_destroy(hash_table_t *table); -void *hash_table_get(hash_table_t *table, void *key); -void hash_table_put(hash_table_t *table, void *key, void *value); -void hash_table_remove(hash_table_t *table, void *key); +struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function); +void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb); +void *hash_table_get(struct hash_table_t *table, void *key); +void hash_table_put(struct hash_table_t *table, void *key, void *value); +void hash_table_remove(struct hash_table_t *table, void *key); /* Device caps */ -#define MAX_PALETTES 256 +#define MAX_PALETTES 65536 #define MAX_STREAMS 16 #define MAX_TEXTURES 8 #define MAX_FRAGMENT_SAMPLERS 16 @@ -105,52 +106,54 @@ extern const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S]; typedef enum _WINELOOKUP { WINELOOKUP_WARPPARAM = 0, - WINELOOKUP_MAGFILTER = 1, - MAX_LOOKUPS = 2 + MAX_LOOKUPS = 1 } WINELOOKUP; extern int minLookup[MAX_LOOKUPS]; extern int maxLookup[MAX_LOOKUPS]; extern DWORD *stateLookup[MAX_LOOKUPS]; -extern DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1]; +typedef DWORD magLookup_t[WINED3DTEXF_ANISOTROPIC + 1]; +extern magLookup_t magLookup; +extern magLookup_t magLookup_noFilter; -typedef struct _WINED3DGLTYPE { - int d3dType; - GLint size; - GLenum glType; - GLboolean normalized; - int typesize; -} WINED3DGLTYPE; +typedef DWORD minMipLookup_t[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1]; +extern minMipLookup_t minMipLookup; +extern minMipLookup_t minMipLookup_noFilter; -/* NOTE: Make sure these are in the correct numerical order. (see /include/wined3d_types.h) */ -static WINED3DGLTYPE const glTypeLookup[WINED3DDECLTYPE_UNUSED] = { - {WINED3DDECLTYPE_FLOAT1, 1, GL_FLOAT , GL_FALSE ,sizeof(float)}, - {WINED3DDECLTYPE_FLOAT2, 2, GL_FLOAT , GL_FALSE ,sizeof(float)}, - {WINED3DDECLTYPE_FLOAT3, 3, GL_FLOAT , GL_FALSE ,sizeof(float)}, - {WINED3DDECLTYPE_FLOAT4, 4, GL_FLOAT , GL_FALSE ,sizeof(float)}, - {WINED3DDECLTYPE_D3DCOLOR, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)}, - {WINED3DDECLTYPE_UBYTE4, 4, GL_UNSIGNED_BYTE , GL_FALSE ,sizeof(BYTE)}, - {WINED3DDECLTYPE_SHORT2, 2, GL_SHORT , GL_FALSE ,sizeof(short int)}, - {WINED3DDECLTYPE_SHORT4, 4, GL_SHORT , GL_FALSE ,sizeof(short int)}, - {WINED3DDECLTYPE_UBYTE4N, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)}, - {WINED3DDECLTYPE_SHORT2N, 2, GL_SHORT , GL_TRUE ,sizeof(short int)}, - {WINED3DDECLTYPE_SHORT4N, 4, GL_SHORT , GL_TRUE ,sizeof(short int)}, - {WINED3DDECLTYPE_USHORT2N, 2, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)}, - {WINED3DDECLTYPE_USHORT4N, 4, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)}, - {WINED3DDECLTYPE_UDEC3, 3, GL_UNSIGNED_SHORT , GL_FALSE ,sizeof(short int)}, - {WINED3DDECLTYPE_DEC3N, 3, GL_SHORT , GL_TRUE ,sizeof(short int)}, - /* We should do an extension check for NV_HALF_FLOAT. However, without NV_HALF_FLOAT - * we won't be able to load the data at all, so at least for the moment it wouldn't - * gain us much. */ - {WINED3DDECLTYPE_FLOAT16_2, 2, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)}, - {WINED3DDECLTYPE_FLOAT16_4, 4, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)}}; +void init_type_lookup(WineD3D_GL_Info *gl_info); +#define WINED3D_ATR_TYPE(type) GLINFO_LOCATION.glTypeLookup[type].d3dType +#define WINED3D_ATR_SIZE(type) GLINFO_LOCATION.glTypeLookup[type].size +#define WINED3D_ATR_GLTYPE(type) GLINFO_LOCATION.glTypeLookup[type].glType +#define WINED3D_ATR_NORMALIZED(type) GLINFO_LOCATION.glTypeLookup[type].normalized +#define WINED3D_ATR_TYPESIZE(type) GLINFO_LOCATION.glTypeLookup[type].typesize -#define WINED3D_ATR_TYPE(type) glTypeLookup[type].d3dType -#define WINED3D_ATR_SIZE(type) glTypeLookup[type].size -#define WINED3D_ATR_GLTYPE(type) glTypeLookup[type].glType -#define WINED3D_ATR_NORMALIZED(type) glTypeLookup[type].normalized -#define WINED3D_ATR_TYPESIZE(type) glTypeLookup[type].typesize +/* float_16_to_32() and float_32_to_16() (see implementation in + * surface_base.c) convert 16 bit floats in the FLOAT16 data type + * to standard C floats and vice versa. They do not depend on the encoding + * of the C float, so they are platform independent, but slow. On x86 and + * other IEEE 754 compliant platforms the conversion can be accelerated by + * bit shifting the exponent and mantissa. There are also some SSE-based + * assembly routines out there. + * + * See GL_NV_half_float for a reference of the FLOAT16 / GL_HALF format + */ +static inline float float_16_to_32(const unsigned short *in) { + const unsigned short s = ((*in) & 0x8000); + const unsigned short e = ((*in) & 0x7C00) >> 10; + const unsigned short m = (*in) & 0x3FF; + const float sgn = (s ? -1.0 : 1.0); + + if(e == 0) { + if(m == 0) return sgn * 0.0; /* +0.0 or -0.0 */ + else return sgn * pow(2, -14.0) * ( (float) m / 1024.0); + } else if(e < 31) { + return sgn * pow(2, (float) e-15.0) * (1.0 + ((float) m / 1024.0)); + } else { + if(m == 0) return sgn / 0.0; /* +INF / -INF */ + else return 0.0 / 0.0; /* NAN */ + } +} /** * Settings @@ -174,7 +177,8 @@ static WINED3DGLTYPE const glTypeLookup[WINED3DDECLTYPE_UNUSED] = { #define SHADER_ARB 1 #define SHADER_GLSL 2 -#define SHADER_NONE 3 +#define SHADER_ATI 3 +#define SHADER_NONE 4 #define RTL_DISABLE -1 #define RTL_AUTO 0 @@ -199,6 +203,7 @@ typedef struct wined3d_settings_s { /* Memory tracking and object counting */ unsigned int emulated_textureram; char *logo; + int allow_multisampling; } wined3d_settings_t; extern wined3d_settings_t wined3d_settings; @@ -206,15 +211,48 @@ extern wined3d_settings_t wined3d_settings; /* Shader backends */ struct SHADER_OPCODE_ARG; +#define SHADER_PGMSIZE 65535 +typedef struct SHADER_BUFFER { + char* buffer; + unsigned int bsize; + unsigned int lineNo; + BOOL newline; +} SHADER_BUFFER; + +struct shader_caps { + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; + + DWORD PixelShaderVersion; + float PixelShader1xMaxValue; + + WINED3DVSHADERCAPS2_0 VS20Caps; + WINED3DPSHADERCAPS2_0 PS20Caps; + + DWORD MaxVShaderInstructionsExecuted; + DWORD MaxPShaderInstructionsExecuted; + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; +}; + typedef struct { void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS); void (*shader_select_depth_blt)(IWineD3DDevice *iface); + void (*shader_deselect_depth_blt)(IWineD3DDevice *iface); void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_cleanup)(IWineD3DDevice *iface); void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg); void (*shader_destroy)(IWineD3DBaseShader *iface); + HRESULT (*shader_alloc_private)(IWineD3DDevice *iface); + void (*shader_free_private)(IWineD3DDevice *iface); + BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface); + void (*shader_generate_pshader)(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer); + void (*shader_generate_vshader)(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer); + void (*shader_get_caps)(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *caps); + BOOL (*shader_conv_supported)(WINED3DFORMAT conv); } shader_backend_t; +extern const shader_backend_t atifs_shader_backend; extern const shader_backend_t glsl_shader_backend; extern const shader_backend_t arb_program_shader_backend; extern const shader_backend_t none_shader_backend; @@ -271,7 +309,6 @@ extern int num_lock; /* Maximum number of constants provided to the shaders */ #define HIGHEST_TRANSFORMSTATE 512 /* Highest value in WINED3DTRANSFORMSTATETYPE */ -#define MAX_PALETTES 256 /* Checking of API calls */ /* --------------------- */ @@ -411,6 +448,13 @@ void primitiveDeclarationConvertToStridedData( DWORD get_flexible_vertex_size(DWORD d3dvtVertexType); +typedef void (WINE_GLAPI *glAttribFunc)(void *data); +typedef void (WINE_GLAPI *glTexAttribFunc)(GLuint unit, void *data); +extern glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED]; +extern glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED]; +extern glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED]; +extern glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED]; + #define eps 1e-8 #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \ @@ -472,12 +516,62 @@ typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, struct StateEntry { - DWORD representative; - APPLYSTATEFUNC apply; + DWORD representative; + APPLYSTATEFUNC apply; }; -/* Global state table */ -extern const struct StateEntry StateTable[]; +struct StateEntryTemplate +{ + DWORD state; + struct StateEntry content; + GL_SupportedExt extension; +}; + +struct fragment_caps { + DWORD PrimitiveMiscCaps; + + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; +}; + +struct fragment_pipeline { + void (*enable_extension)(IWineD3DDevice *iface, BOOL enable); + void (*get_caps)(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *caps); + HRESULT (*alloc_private)(IWineD3DDevice *iface); + void (*free_private)(IWineD3DDevice *iface); + BOOL (*conv_supported)(WINED3DFORMAT conv); + const struct StateEntryTemplate *states; + BOOL ffp_proj_control; +}; + +extern const struct StateEntryTemplate misc_state_template[]; +extern const struct StateEntryTemplate ffp_vertexstate_template[]; +extern const struct fragment_pipeline ffp_fragment_pipeline; +extern const struct fragment_pipeline atifs_fragment_pipeline; +extern const struct fragment_pipeline arbfp_fragment_pipeline; +extern const struct fragment_pipeline nvts_fragment_pipeline; +extern const struct fragment_pipeline nvrc_fragment_pipeline; + +/* "Base" state table */ +void compile_state_table(struct StateEntry *StateTable, + APPLYSTATEFUNC **dev_multistate_funcs, + WineD3D_GL_Info *gl_info, + const struct StateEntryTemplate *vertex, + const struct fragment_pipeline *fragment, + const struct StateEntryTemplate *misc); + +/* Shaders for color conversions in blits */ +struct blit_shader { + HRESULT (*alloc_private)(IWineD3DDevice *iface); + void (*free_private)(IWineD3DDevice *iface); + HRESULT (*set_shader)(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height); + void (*unset_shader)(IWineD3DDevice *iface); + BOOL (*conv_supported)(WINED3DFORMAT conv); +}; + +extern const struct blit_shader ffp_blit; +extern const struct blit_shader arbfp_blit; /* The new context manager that should deal with onscreen and offscreen rendering */ struct WineD3DContext { @@ -494,8 +588,8 @@ struct WineD3DContext { IWineD3DSurface *surface; DWORD tid; /* Thread ID which owns this context at the moment */ - /* Stores some inforation about the context state for optimization */ - GLint last_draw_buffer; + /* Stores some information about the context state for optimization */ + BOOL draw_buffer_dirty; BOOL last_was_rhw; /* true iff last draw_primitive was in xyzrhw mode */ BOOL last_was_pshader; BOOL last_was_vshader; @@ -506,20 +600,30 @@ struct WineD3DContext { unsigned char num_untracked_materials; GLenum untracked_materials[2]; BOOL last_was_blit, last_was_ckey; + UINT blit_w, blit_h; char texShaderBumpMap; BOOL fog_coord; + char *vshader_const_dirty, *pshader_const_dirty; + /* The actual opengl context */ HGLRC glCtx; HWND win_handle; HDC hdc; HPBUFFERARB pbuffer; BOOL isPBuffer; + GLint aux_buffers; + + /* FBOs */ + struct list fbo_list; + struct fbo_entry *current_fbo; + GLuint src_fbo; + GLuint dst_fbo; }; typedef enum ContextUsage { CTXUSAGE_RESOURCELOAD = 1, /* Only loads textures: No State is applied */ - CTXUSAGE_DRAWPRIM = 2, /* OpenGL states are set up for blitting DirectDraw surfacs */ + 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; @@ -527,7 +631,12 @@ typedef enum ContextUsage { void ActivateContext(IWineD3DDeviceImpl *device, IWineD3DSurface *target, ContextUsage usage); WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms); void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context); -void apply_fbo_state(IWineD3DDevice *iface); +void context_bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo); +void context_attach_depth_stencil_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer); +void context_attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface); + +void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain); +HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain); /* Macros for doing basic GPU detection based on opengl capabilities */ #define WINE_D3D6_CAPABLE(gl_info) (gl_info->supported[ARB_MULTITEXTURE]) @@ -550,6 +659,7 @@ struct PLIGHTINFOEL { LONG glIndex; BOOL changed; BOOL enabledChanged; + BOOL enabled; /* Converted parms to speed up swapping lights */ float lightPosn[4]; @@ -566,14 +676,21 @@ extern const WINED3DLIGHT WINED3D_default_light; typedef struct WineD3D_PixelFormat { int iPixelFormat; /* WGL pixel format */ + int iPixelType; /* WGL pixel type e.g. WGL_TYPE_RGBA_ARB, WGL_TYPE_RGBA_FLOAT_ARB or WGL_TYPE_COLORINDEX_ARB */ int redSize, greenSize, blueSize, alphaSize; int depthSize, stencilSize; + BOOL windowDrawable; + BOOL pbufferDrawable; + BOOL doubleBuffer; + int auxBuffers; + int numSamples; } WineD3D_PixelFormat; /* The adapter structure */ -typedef struct GLPixelFormatDesc GLPixelFormatDesc; struct WineD3DAdapter { + UINT num; + BOOL opengl; POINT monitorPoint; WineD3D_GL_Info gl_info; const char *driver; @@ -581,6 +698,7 @@ struct WineD3DAdapter WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ int nCfgs; WineD3D_PixelFormat *cfgs; + BOOL brokenStencil; /* Set on cards which only offer mixed depth+stencil */ unsigned int TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */ unsigned int UsedTextureRam; }; @@ -605,6 +723,67 @@ struct WineD3DRectPatch HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, struct WineD3DRectPatch *patch); +enum projection_types +{ + proj_none = 0, + proj_count3 = 1, + proj_count4 = 2 +}; + +enum tex_types +{ + tex_1d = 0, + tex_2d = 1, + tex_3d = 2, + tex_cube = 3, + tex_rect = 4 +}; + +enum dst_arg +{ + resultreg = 0, + tempreg = 1 +}; + +/***************************************************************************** + * Fixed function pipeline replacements + */ +struct texture_stage_op +{ + unsigned cop : 5, aop : 5; +#define ARG_UNUSED 0x3f + unsigned carg1 : 6, carg2 : 6, carg0 : 6; + unsigned tex_type : 3; + unsigned dst : 1; /* Total of 32 bits */ + unsigned aarg1 : 6, aarg2 : 6, aarg0 : 6; + unsigned projected : 2; + unsigned padding : 12; /* Total of 64 bits */ + WINED3DFORMAT color_correction; +}; + +struct ffp_settings { + struct texture_stage_op op[MAX_TEXTURES]; + enum { + FOG_OFF, + FOG_LINEAR, + FOG_EXP, + FOG_EXP2 + } fog; + /* Use an int instead of a char to get dword alignment */ + unsigned int sRGB_write; +}; + +struct ffp_desc +{ + struct ffp_settings settings; +}; + +void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *settings, BOOL ignore_textype); +struct ffp_desc *find_ffp_shader(struct hash_table_t *fragment_shaders, struct ffp_settings *settings); +void add_ffp_shader(struct hash_table_t *shaders, struct ffp_desc *desc); +BOOL ffp_program_key_compare(void *keya, void *keyb); +unsigned int ffp_program_key_hash(void *key); + /***************************************************************************** * IWineD3D implementation structure */ @@ -656,12 +835,23 @@ struct IWineD3DDeviceImpl int vs_selected_mode; int ps_selected_mode; const shader_backend_t *shader_backend; - hash_table_t *glsl_program_lookup; + void *shader_priv; + void *fragment_priv; + void *blit_priv; + struct StateEntry StateTable[STATE_HIGHEST + 1]; + /* Array of functions for states which are handled by more than one pipeline part */ + APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1]; + const struct fragment_pipeline *frag_pipe; + const struct blit_shader *blitter; + + unsigned int max_ffp_textures, max_ffp_texture_stages; /* To store */ BOOL view_ident; /* true iff view matrix is identity */ BOOL untransformed; BOOL vertexBlendUsed; /* To avoid needless setting of the blend matrices */ +#define DDRAW_PITCH_ALIGNMENT 8 +#define D3D8_PITCH_ALIGNMENT 4 unsigned char surface_alignment; /* Line Alignment of surfaces */ /* State block related */ @@ -679,13 +869,12 @@ struct IWineD3DDeviceImpl UINT NumberOfSwapChains; struct list resources; /* a linked list to track resources created by the device */ + struct list shaders; /* a linked list to track shaders (pixel and vertex) */ + unsigned int highest_dirty_ps_const, highest_dirty_vs_const; /* Render Target Support */ IWineD3DSurface **render_targets; IWineD3DSurface *auto_depth_stencil_buffer; - IWineD3DSurface **fbo_color_attachments; - IWineD3DSurface *fbo_depth_attachment; - IWineD3DSurface *stencilBufferTarget; /* Caches to avoid unneeded context changes */ @@ -693,17 +882,18 @@ struct IWineD3DDeviceImpl IWineD3DSwapChain *lastActiveSwapChain; /* palettes texture management */ - PALETTEENTRY palettes[MAX_PALETTES][256]; + UINT NumberOfPalettes; + PALETTEENTRY **palettes; UINT currentPalette; UINT paletteConversionShader; /* For rendering to a texture using glCopyTexImage */ BOOL render_offscreen; - WINED3D_DEPTHCOPYSTATE depth_copy_state; - GLuint fbo; - GLuint src_fbo; - GLuint dst_fbo; GLenum *draw_buffers; + GLuint depth_blt_texture; + GLuint depth_blt_rb; + UINT depth_blt_rb_w; + UINT depth_blt_rb_h; /* Cursor management */ BOOL bCursorVisible; @@ -736,11 +926,8 @@ struct IWineD3DDeviceImpl BOOL softwareVertexProcessing; /* DirectDraw stuff */ - HWND ddraw_window; - IWineD3DSurface *ddraw_primary; DWORD ddraw_width, ddraw_height; WINED3DFORMAT ddraw_format; - BOOL ddraw_fullscreen; /* Final position fixup constant */ float posFixup[4]; @@ -771,8 +958,11 @@ struct IWineD3DDeviceImpl struct WineD3DRectPatch *currentPatch; }; -extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl; +extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl, IWineD3DDevice_DirtyConst_Vtbl; +HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, + CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color, + float Z, DWORD Stencil); void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This); void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state); static inline BOOL isStateDirty(WineD3DContext *context, DWORD state) { @@ -835,6 +1025,17 @@ typedef struct IWineD3DResourceImpl /***************************************************************************** * IWineD3DVertexBuffer implementation structure (extends IWineD3DResourceImpl) */ +enum vbo_conversion_type { + CONV_NONE = 0, + CONV_D3DCOLOR = 1, + CONV_POSITIONT = 2, + CONV_FLOAT16_2 = 3 /* Also handles FLOAT16_4 */ + + /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other + * fixed function semantics as D3DCOLOR or FLOAT16 + */ +}; + typedef struct IWineD3DVertexBufferImpl { /* IUnknown & WineD3DResource Information */ @@ -848,22 +1049,28 @@ typedef struct IWineD3DVertexBufferImpl GLuint vbo; BYTE Flags; LONG bindCount; + LONG vbo_size; + GLenum vbo_usage; UINT dirtystart, dirtyend; LONG lockcount; LONG declChanges, draws; /* Last description of the buffer */ - WineDirect3DVertexStridedData strided; + DWORD stride; /* 0 if no conversion */ + enum vbo_conversion_type *conv_map; /* NULL if no conversion */ + + /* Extra load offsets, for FLOAT16 conversion */ + DWORD *conv_shift; /* NULL if no shifted conversion */ + DWORD conv_stride; /* 0 if no shifted conversion */ } IWineD3DVertexBufferImpl; extern const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl; -#define VBFLAG_LOAD 0x01 /* Data is written from allocatedMemory to the VBO */ -#define VBFLAG_OPTIMIZED 0x02 /* Optimize has been called for the VB */ -#define VBFLAG_DIRTY 0x04 /* Buffer data has been modified */ -#define VBFLAG_HASDESC 0x08 /* A vertex description has been found */ -#define VBFLAG_VBOCREATEFAIL 0x10 /* An attempt to create a vbo has failed */ +#define VBFLAG_OPTIMIZED 0x01 /* Optimize has been called for the VB */ +#define VBFLAG_DIRTY 0x02 /* Buffer data has been modified */ +#define VBFLAG_HASDESC 0x04 /* A vertex description has been found */ +#define VBFLAG_CREATEVBO 0x08 /* Attempt to create a VBO next PreLoad */ /***************************************************************************** * IWineD3DIndexBuffer implementation structure (extends IWineD3DResourceImpl) @@ -923,6 +1130,8 @@ typedef struct IWineD3DBaseTextureClass UINT srgb_mode_change_count; WINED3DFORMAT shader_conversion_group; float pow2Matrix[16]; + minMipLookup_t *minMipLookup; + magLookup_t *magLookup; } IWineD3DBaseTextureClass; typedef struct IWineD3DBaseTextureImpl @@ -949,6 +1158,8 @@ typedef struct IWineD3DTextureImpl UINT width; UINT height; + UINT target; + BOOL cond_np2; } IWineD3DTextureImpl; @@ -1050,6 +1261,15 @@ typedef struct { UINT height; } renderbuffer_entry_t; +struct fbo_entry +{ + struct list entry; + IWineD3DSurface **render_targets; + IWineD3DSurface *depth_stencil; + BOOL attached; + GLuint id; +}; + /***************************************************************************** * IWineD3DClipp implementation structure */ @@ -1085,6 +1305,10 @@ struct IWineD3DSurfaceImpl UINT pow2Width; UINT pow2Height; + float heightscale; + + /* A method to retrieve the drawable size. Not in the Vtable to make it changeable */ + void (*get_drawable_size)(IWineD3DSurfaceImpl *This, UINT *width, UINT *height); /* Oversized texture */ RECT glRect; @@ -1118,6 +1342,13 @@ struct IWineD3DSurfaceImpl /* DirectDraw clippers */ IWineD3DClipper *clipper; + + /* DirectDraw Overlay handling */ + RECT overlay_srcrect; + RECT overlay_destrect; + IWineD3DSurfaceImpl *overlay_dest; + struct list overlays; + struct list overlay_entry; }; extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl; @@ -1161,26 +1392,37 @@ void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface); const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface); +void get_drawable_size_swapchain(IWineD3DSurfaceImpl *This, UINT *width, UINT *height); +void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height); +void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height); +void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height); + +void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back); + /* 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 */ -#define SFLAG_DISCARD 0x00000010 /* ??? */ -#define SFLAG_LOCKED 0x00000020 /* Surface is locked atm */ -#define SFLAG_INTEXTURE 0x00000040 /* The GL texture contains the newest surface content */ -#define SFLAG_INDRAWABLE 0x00000080 /* The gl drawable contains the most up to date data */ -#define SFLAG_INSYSMEM 0x00000100 /* The system memory copy is most up to date */ -#define SFLAG_NONPOW2 0x00000200 /* Surface sizes are not a power of 2 */ -#define SFLAG_DYNLOCK 0x00000400 /* Surface is often locked by the app */ -#define SFLAG_DYNCHANGE 0x00000C00 /* Surface contents are changed very often, implies DYNLOCK */ -#define SFLAG_DCINUSE 0x00001000 /* Set between GetDC and ReleaseDC calls */ -#define SFLAG_LOST 0x00002000 /* Surface lost flag for DDraw */ -#define SFLAG_USERPTR 0x00004000 /* The application allocated the memory for this surface */ -#define SFLAG_GLCKEY 0x00008000 /* The gl texture was created with a color key */ -#define SFLAG_CLIENT 0x00010000 /* GL_APPLE_client_storage is used on that texture */ -#define SFLAG_ALLOCATED 0x00020000 /* A gl texture is allocated for this surface */ -#define SFLAG_PBO 0x00040000 /* Has a PBO attached for speeding up data transfers for dynamically locked surfaces */ +#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 */ +#define SFLAG_DISCARD 0x00000010 /* ??? */ +#define SFLAG_LOCKED 0x00000020 /* Surface is locked atm */ +#define SFLAG_INTEXTURE 0x00000040 /* The GL texture contains the newest surface content */ +#define SFLAG_INDRAWABLE 0x00000080 /* The gl drawable contains the most up to date data */ +#define SFLAG_INSYSMEM 0x00000100 /* The system memory copy is most up to date */ +#define SFLAG_NONPOW2 0x00000200 /* Surface sizes are not a power of 2 */ +#define SFLAG_DYNLOCK 0x00000400 /* Surface is often locked by the app */ +#define SFLAG_DYNCHANGE 0x00000C00 /* Surface contents are changed very often, implies DYNLOCK */ +#define SFLAG_DCINUSE 0x00001000 /* Set between GetDC and ReleaseDC calls */ +#define SFLAG_LOST 0x00002000 /* Surface lost flag for DDraw */ +#define SFLAG_USERPTR 0x00004000 /* The application allocated the memory for this surface */ +#define SFLAG_GLCKEY 0x00008000 /* The gl texture was created with a color key */ +#define SFLAG_CLIENT 0x00010000 /* GL_APPLE_client_storage is used on that texture */ +#define SFLAG_ALLOCATED 0x00020000 /* A gl texture is allocated for this surface */ +#define SFLAG_PBO 0x00040000 /* Has a PBO attached for speeding up data transfers for dynamically locked surfaces */ +#define SFLAG_NORMCOORD 0x00080000 /* Set if the GL texture coords are normalized(non-texture rectangle) */ +#define SFLAG_DS_ONSCREEN 0x00100000 /* Is a depth stencil, last modified onscreen */ +#define SFLAG_DS_OFFSCREEN 0x00200000 /* Is a depth stencil, last modified offscreen */ +#define SFLAG_INOVERLAYDRAW 0x00400000 /* Overlay drawing is in progress. Recursion prevention */ /* In some conditions the surface memory must not be freed: * SFLAG_OVERSIZE: Not all data can be kept in GL @@ -1192,19 +1434,23 @@ const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface); * 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 | \ - SFLAG_DIBSECTION | \ - SFLAG_LOCKED | \ - SFLAG_DYNLOCK | \ - SFLAG_DYNCHANGE | \ - SFLAG_USERPTR | \ - SFLAG_PBO | \ - SFLAG_CLIENT) +#define SFLAG_DONOTFREE (SFLAG_OVERSIZE | \ + SFLAG_CONVERTED | \ + SFLAG_DIBSECTION | \ + SFLAG_LOCKED | \ + SFLAG_DYNLOCK | \ + SFLAG_DYNCHANGE | \ + SFLAG_USERPTR | \ + SFLAG_PBO | \ + SFLAG_CLIENT) + +#define SFLAG_LOCATIONS (SFLAG_INSYSMEM | \ + SFLAG_INTEXTURE | \ + SFLAG_INDRAWABLE) + +#define SFLAG_DS_LOCATIONS (SFLAG_DS_ONSCREEN | \ + SFLAG_DS_OFFSCREEN) -#define SFLAG_LOCATIONS (SFLAG_INSYSMEM | \ - SFLAG_INTEXTURE | \ - SFLAG_INDRAWABLE) BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]); typedef enum { @@ -1228,11 +1474,14 @@ typedef enum { CONVERT_V16U16, CONVERT_A4L4, CONVERT_R32F, - CONVERT_R16F + CONVERT_R16F, + CONVERT_G16R16, } 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); +BOOL palette9_changed(IWineD3DSurfaceImpl *This); + /***************************************************************************** * IWineD3DVertexDeclaration implementation structure */ @@ -1257,6 +1506,7 @@ typedef struct IWineD3DVertexDeclarationImpl { DWORD streams[MAX_STREAMS]; UINT num_streams; BOOL position_transformed; + BOOL half_float_conv_needed; /* Ordered array of declaration types that need swizzling in a vshader */ attrib_declaration swizzled_attribs[MAX_ATTRIBS]; @@ -1389,9 +1639,6 @@ struct IWineD3DStateBlockImpl /* Sampler States */ DWORD samplerState[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1]; - /* Current GLSL Shader Program */ - struct glsl_shader_prog_link *glsl_program; - /* Scissor test rectangle */ RECT scissorRect; @@ -1434,6 +1681,15 @@ extern void stateblock_copy( extern const IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl; +/* 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 + */ +enum query_state { + QUERY_CREATED, + QUERY_SIGNALLED, + QUERY_BUILDING +}; /***************************************************************************** * IWineD3DQueryImpl implementation structure (extends IUnknown) */ @@ -1451,6 +1707,7 @@ typedef struct IWineD3DQueryImpl #endif /* IWineD3DQuery fields */ + enum query_state state; WINED3DQUERYTYPE type; /* TODO: Think about using a IUnknown instead of a void* */ void *extendedData; @@ -1459,6 +1716,8 @@ typedef struct IWineD3DQueryImpl } IWineD3DQueryImpl; extern const IWineD3DQueryVtbl IWineD3DQuery_Vtbl; +extern const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl; +extern const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl; /* Datastructures for IWineD3DQueryImpl.extendedData */ typedef struct WineQueryOcclusionData { @@ -1491,6 +1750,7 @@ typedef struct IWineD3DSwapChainImpl WINED3DPRESENT_PARAMETERS presentParms; DWORD orig_width, orig_height; WINED3DFORMAT orig_fmt; + WINED3DGAMMARAMP orig_gamma; long prev_time, frames; /* Performance tracking */ unsigned int vSyncCounter; @@ -1502,6 +1762,21 @@ typedef struct IWineD3DSwapChainImpl } IWineD3DSwapChainImpl; extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl; +const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl; +void x11_copy_to_screen(IWineD3DSwapChainImpl *This, LPRECT rc); + +HRESULT WINAPI IWineD3DBaseSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj); +ULONG WINAPI IWineD3DBaseSwapChainImpl_AddRef(IWineD3DSwapChain *iface); +ULONG WINAPI IWineD3DBaseSwapChainImpl_Release(IWineD3DSwapChain *iface); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp); +HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp); WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface); @@ -1529,16 +1804,23 @@ const char *debug_fbostatus(GLenum status); const char *debug_glerror(GLenum error); const char *debug_d3dbasis(WINED3DBASISTYPE basis); const char *debug_d3ddegree(WINED3DDEGREETYPE order); +const char* debug_d3dtop(WINED3DTEXTUREOP d3dtop); /* Routines for GL <-> D3D values */ GLenum StencilOp(DWORD op); GLenum CompareFunc(DWORD func); -void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3); -void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx); -void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype); +BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3); +void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx, DWORD dst); +void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype, BOOL ffp_can_disable_proj); +void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); +void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); +void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); +void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height); GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain); +void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location); +void surface_load_ds_location(IWineD3DSurface *iface, DWORD location); BOOL getColorBits(WINED3DFORMAT fmt, short *redSize, short *greenSize, short *blueSize, short *alphaSize, short *totalSize); BOOL getDepthStencilBits(WINED3DFORMAT fmt, short *depthSize, short *stencilSize); @@ -1565,6 +1847,7 @@ unsigned int count_bits(unsigned int mask); extern DWORD WINAPI IWineD3DResourceImpl_SetPriority(IWineD3DResource *iface, DWORD PriorityNew); extern DWORD WINAPI IWineD3DResourceImpl_GetPriority(IWineD3DResource *iface); extern void WINAPI IWineD3DResourceImpl_PreLoad(IWineD3DResource *iface); + extern void WINAPI IWineD3DResourceImpl_UnLoad(IWineD3DResource *iface); extern WINED3DRESOURCETYPE WINAPI IWineD3DResourceImpl_GetType(IWineD3DResource *iface); /*** class static members ***/ void IWineD3DResourceImpl_CleanUp(IWineD3DResource *iface); @@ -1582,6 +1865,7 @@ unsigned int count_bits(unsigned int mask); extern DWORD WINAPI IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew); extern DWORD WINAPI IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface); extern void WINAPI IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface); + extern void WINAPI IWineD3DBaseTextureImpl_UnLoad(IWineD3DBaseTexture *iface); extern WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface); /*** IWineD3DBaseTexture methods ***/ extern DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew); @@ -1596,40 +1880,12 @@ unsigned int count_bits(unsigned int mask); extern BYTE* WINAPI IWineD3DVertexBufferImpl_GetMemory(IWineD3DVertexBuffer* iface, DWORD iOffset, GLint *vbo); extern HRESULT WINAPI IWineD3DVertexBufferImpl_ReleaseMemory(IWineD3DVertexBuffer* iface); extern HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface); - extern HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface); extern void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface, const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]); /*** class static members ***/ void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface); typedef void (*SHADER_HANDLER) (struct SHADER_OPCODE_ARG*); -/* Struct to maintain a list of GLSL shader programs and their associated pixel and - * vertex shaders. A list of this type is maintained on the DeviceImpl, and is only - * used if the user is using GLSL shaders. */ -struct glsl_shader_prog_link { - struct list vshader_entry; - struct list pshader_entry; - GLhandleARB programId; - GLhandleARB *vuniformF_locations; - GLhandleARB *puniformF_locations; - GLhandleARB vuniformI_locations[MAX_CONST_I]; - GLhandleARB puniformI_locations[MAX_CONST_I]; - GLhandleARB posFixup_location; - GLhandleARB bumpenvmat_location; - GLhandleARB luminancescale_location; - GLhandleARB luminanceoffset_location; - GLhandleARB srgb_comparison_location; - GLhandleARB srgb_mul_low_location; - GLhandleARB ycorrection_location; - GLhandleARB vshader; - GLhandleARB pshader; -}; - -typedef struct { - GLhandleARB vshader; - GLhandleARB pshader; -} glsl_program_key_t; - /* TODO: Make this dynamic, based on shader limits ? */ #define MAX_REG_ADDR 1 #define MAX_REG_TEMP 32 @@ -1663,11 +1919,12 @@ typedef struct shader_reg_maps { char packed_output[MAX_REG_OUTPUT]; /* vertex >= 3.0 */ char attributes[MAX_ATTRIBS]; /* vertex */ char labels[MAX_LABELS]; /* pixel, vertex */ + DWORD texcoord_mask[MAX_REG_TEXCRD]; /* vertex < 3.0 */ /* Sampler usage tokens * Use 0 as default (bit 31 is always 1 on a valid token) */ DWORD samplers[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; - char bumpmat, luminanceparams; + BOOL bumpmat[MAX_TEXTURES], luminanceparams[MAX_TEXTURES]; char usesnrm, vpos, usesdsy; char usesrelconstF; @@ -1679,14 +1936,6 @@ typedef struct shader_reg_maps { } shader_reg_maps; -#define SHADER_PGMSIZE 65535 -typedef struct SHADER_BUFFER { - char* buffer; - unsigned int bsize; - unsigned int lineNo; - BOOL newline; -} SHADER_BUFFER; - /* Undocumented opcode controls */ #define INST_CONTROLS_SHIFT 16 #define INST_CONTROLS_MASK 0x00ff0000 @@ -1746,18 +1995,22 @@ typedef struct SHADER_PARSE_STATE { DWORD texcoord_w[2]; } SHADER_PARSE_STATE; +#ifdef __GNUC__ +#define PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args))) +#else +#define PRINTF_ATTR(fmt,args) +#endif + /* Base Shader utility functions. * (may move callers into the same file in the future) */ extern int shader_addline( SHADER_BUFFER* buffer, - const char* fmt, ...); + const char* fmt, ...) PRINTF_ATTR(2,3); extern const SHADER_OPCODE* shader_get_opcode( IWineD3DBaseShader *iface, const DWORD code); -void delete_glsl_program_entry(IWineD3DDevice *iface, struct glsl_shader_prog_link *entry); - /* Vertex shader utility functions */ extern BOOL vshader_get_input( IWineD3DVertexShader* iface, @@ -1770,12 +2023,6 @@ extern BOOL vshader_input_is_color( extern HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object); -/* ARB_[vertex/fragment]_program helper functions */ -extern void shader_arb_load_constants( - IWineD3DDevice* device, - char usePixelShader, - char useVertexShader); - /* ARB shader program Prototypes */ extern void shader_hw_def(SHADER_OPCODE_ARG *arg); @@ -1815,10 +2062,6 @@ extern void vshader_hw_rsq_rcp(SHADER_OPCODE_ARG* arg); /* GLSL helper functions */ extern void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG *arg); -extern void shader_glsl_load_constants( - IWineD3DDevice* device, - char usePixelShader, - char useVertexShader); /** The following translate DirectX pixel/vertex shader opcodes to GLSL lines */ extern void shader_glsl_cross(SHADER_OPCODE_ARG* arg); @@ -1877,10 +2120,6 @@ extern void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg); -extern void pshader_glsl_input_pack( - SHADER_BUFFER* buffer, - semantic* semantics_out, - IWineD3DPixelShader *iface); /***************************************************************************** * IDirect3DBaseShader implementation structure @@ -1924,6 +2163,7 @@ typedef struct IWineD3DBaseShaderClass /* Pointer to the parent device */ IWineD3DDevice *device; + struct list shader_list_entry; } IWineD3DBaseShaderClass; @@ -1947,18 +2187,6 @@ extern HRESULT shader_get_registers_used( CONST DWORD* pToken, IWineD3DStateBlockImpl *stateBlock); -extern void shader_generate_glsl_declarations( - IWineD3DBaseShader *iface, - shader_reg_maps* reg_maps, - SHADER_BUFFER* buffer, - WineD3D_GL_Info* gl_info); - -extern void shader_generate_arb_declarations( - IWineD3DBaseShader *iface, - shader_reg_maps* reg_maps, - SHADER_BUFFER* buffer, - WineD3D_GL_Info* gl_info); - extern void shader_generate_main( IWineD3DBaseShader *iface, SHADER_BUFFER* buffer, @@ -1988,15 +2216,15 @@ extern int shader_skip_unrecognized( IWineD3DBaseShader* iface, const DWORD* pToken); -extern void print_glsl_info_log( - WineD3D_GL_Info *gl_info, - GLhandleARB obj); - static inline int shader_get_regtype(const DWORD param) { return (((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2)); } +static inline int shader_get_writemask(const DWORD param) { + return param & WINED3DSP_WRITEMASK_ALL; +} + extern unsigned int shader_get_float_offset(const DWORD reg); static inline BOOL shader_is_pshader_version(DWORD token) { @@ -2011,9 +2239,9 @@ static inline BOOL shader_is_comment(DWORD token) { return WINED3DSIO_COMMENT == (token & WINED3DSI_OPCODE_MASK); } -/* TODO: vFace (ps_3_0) */ static inline BOOL shader_is_scalar(DWORD param) { DWORD reg_type = shader_get_regtype(param); + DWORD reg_num; switch (reg_type) { case WINED3DSPR_RASTOUT: @@ -2030,16 +2258,32 @@ static inline BOOL shader_is_scalar(DWORD param) { case WINED3DSPR_PREDICATE: /* p0 */ return TRUE; + case WINED3DSPR_MISCTYPE: + reg_num = param & WINED3DSP_REGNUM_MASK; + switch(reg_num) { + case 0: /* vPos */ + return FALSE; + case 1: /* vFace */ + return TRUE; + default: + return FALSE; + } + default: return FALSE; } } -/* Internally used shader constants. Applications can use constants 0 to GL_LIMITS(vshader_constantsF) - 1, - * so upload them above that - */ -#define ARB_SHADER_PRIVCONST_BASE GL_LIMITS(vshader_constantsF) -#define ARB_SHADER_PRIVCONST_POS ARB_SHADER_PRIVCONST_BASE + 0 +static inline BOOL shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD reg) { + local_constant* lconst; + + if(This->baseShader.load_local_constsF) return FALSE; + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + if(lconst->idx == reg) return TRUE; + } + return FALSE; + +} /***************************************************************************** * IDirect3DVertexShader implementation structure @@ -2064,14 +2308,14 @@ typedef struct IWineD3DVertexShaderImpl { attrib_declaration swizzled_attribs [MAX_ATTRIBS]; UINT num_swizzled_attribs; - /* run time datas... */ + /* run time data... */ VSHADERDATA *data; UINT min_rel_offset, max_rel_offset; UINT rel_offset; UINT recompile_count; #if 0 /* needs reworking */ - /* run time datas */ + /* run time data */ VSHADERINPUTDATA input; VSHADEROUTPUTDATA output; #endif @@ -2089,6 +2333,11 @@ enum vertexprocessing_mode { pretransformed }; +struct stb_const_desc { + char texunit; + UINT const_num; +}; + typedef struct IWineD3DPixelShaderImpl { /* IUnknown parts */ const IWineD3DPixelShaderVtbl *lpVtbl; @@ -2103,14 +2352,15 @@ typedef struct IWineD3DPixelShaderImpl { semantic semantics_in [MAX_REG_INPUT]; DWORD input_reg_map[MAX_REG_INPUT]; BOOL input_reg_used[MAX_REG_INPUT]; + int declared_in_count; /* run time data */ PSHADERDATA *data; /* Some information about the shader behavior */ - char needsbumpmat; - UINT bumpenvmatconst; - UINT luminanceconst; + struct stb_const_desc bumpenvmatconst[MAX_TEXTURES]; + char numbumpenvmatconsts; + struct stb_const_desc luminanceconst[MAX_TEXTURES]; char srgb_enabled; char srgb_mode_hardcoded; UINT srgb_low_const; @@ -2193,5 +2443,7 @@ static inline BOOL use_ps(IWineD3DDeviceImpl *device) { void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect, IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip); +void depth_blt(IWineD3DDevice *iface, GLuint texture, GLsizei w, GLsizei h); +void context_destroy_fbo_entry(IWineD3DDeviceImpl *This, struct fbo_entry *entry); #endif diff --git a/reactos/dll/directx/wine/wined3d/wined3d_private_types.h b/reactos/dll/directx/wine/wined3d/wined3d_private_types.h index 8a7750f8ecd..343244e0214 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private_types.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private_types.h @@ -23,12 +23,12 @@ #ifndef __WINE_WINED3D_TYPES_INTERNAL_H #define __WINE_WINED3D_TYPES_INTERNAL_H -/* Depth copy state */ -typedef enum { - WINED3D_DCS_INITIAL = 0, - WINED3D_DCS_COPY = 1, - WINED3D_DCS_NO_COPY = 2 -} WINED3D_DEPTHCOPYSTATE; +/* 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 /** DCL usage masks **/ #define WINED3DSP_DCL_USAGE_SHIFT 0 diff --git a/reactos/include/psdk/d3d9.h b/reactos/include/psdk/d3d9.h index 0c49041d16a..83839fef5a9 100644 --- a/reactos/include/psdk/d3d9.h +++ b/reactos/include/psdk/d3d9.h @@ -111,9 +111,15 @@ DEFINE_GUID(IID_IDirect3D9, 0x81BDCBCA, 0x64D4, 0x426D, 0xAE, 0x8D, 0xAD, 0x1, 0x47, 0xF4, 0x27, 0x5C); typedef struct IDirect3D9 *LPDIRECT3D9, *PDIRECT3D9; +DEFINE_GUID(IID_IDirect3D9Ex, 0x02177241, 0x69FC, 0x400C, 0x8F, 0xF1, 0x93, 0xA4, 0x4D, 0xF6, 0x86, 0x1D); +typedef struct IDirect3D9Ex *LPDIRECT3D9EX, *PDIRECT3D9EX; + DEFINE_GUID(IID_IDirect3DDevice9, 0xd0223b96, 0xbf7a, 0x43fd, 0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb); typedef struct IDirect3DDevice9 *LPDIRECT3DDEVICE9; +DEFINE_GUID(IID_IDirect3DDevice9Ex, 0xb18b10ce, 0x2649, 0x405a, 0x87, 0xf, 0x95, 0xf7, 0x77, 0xd4, 0x31, 0x3a); +typedef struct IDirect3DDevice9Ex *LPDIRECT3DDEVICE9EX, *PDIRECT3DDEVICE9EX; + DEFINE_GUID(IID_IDirect3DResource9, 0x5eec05d, 0x8f7d, 0x4362, 0xb9, 0x99, 0xd1, 0xba, 0xf3, 0x57, 0xc7, 0x4); typedef struct IDirect3DResource9 *LPDIRECT3DRESOURCE9, *PDIRECT3DRESOURCE9; @@ -234,6 +240,88 @@ DECLARE_INTERFACE_(IDirect3D9,IUnknown) #define IDirect3D9_CreateDevice(p,a,b,c,d,e,f) (p)->CreateDevice(a,b,c,d,e,f) #endif +/***************************************************************************** + * IDirect3D9Ex interface + */ +#define INTERFACE IDirect3D9Ex +DECLARE_INTERFACE_(IDirect3D9Ex,IDirect3D9) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirect3D9 methods ***/ + STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE; + STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE; + STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) PURE; + STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter, D3DFORMAT Format) PURE; + STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter, D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(CheckDeviceType)(THIS_ UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) PURE; + STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) PURE; + STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) PURE; + STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) PURE; + STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) PURE; + STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE; + STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, struct IDirect3DDevice9** ppReturnedDeviceInterface) PURE; + /*** IDirect3D9Ex methods ***/ + STDMETHOD_(UINT, GetAdapterModeCountEx)(THIS_ UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter) PURE; + STDMETHOD(EnumAdapterModesEx)(THIS_ UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) PURE; + STDMETHOD(GetAdapterDisplayModeEx)(THIS_ UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation); + STDMETHOD(CreateDeviceEx)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, struct IDirect3DDevice9Ex **ppReturnedDeviceInterface) PURE; + STDMETHOD(GetAdapterLUID)(THIS_ UINT Adatper, LUID *pLUID) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3D9Ex_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3D9Ex_Release(p) (p)->lpVtbl->Release(p) +/*** IDirect3D9 methods ***/ +#define IDirect3D9Ex_RegisterSoftwareDevice(p,a) (p)->lpVtbl->RegisterSoftwareDevice(p,a) +#define IDirect3D9Ex_GetAdapterCount(p) (p)->lpVtbl->GetAdapterCount(p) +#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c) (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c) +#define IDirect3D9Ex_GetAdapterModeCount(p,a,b) (p)->lpVtbl->GetAdapterModeCount(p,a,b) +#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d) (p)->lpVtbl->EnumAdapterModes(p,a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b) (p)->lpVtbl->GetAdapterDisplayMode(p,a,b) +#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e) (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d) (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d) +#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c) (p)->lpVtbl->GetDeviceCaps(p,a,b,c) +#define IDirect3D9Ex_GetAdapterMonitor(p,a) (p)->lpVtbl->GetAdapterMonitor(p,a) +#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f) +/*** IDirect3D9Ex methods ***/ +#define IDirect3D9Ex_GetAdapterModeCountEx(p,a,b) (p)->lpVtbl->GetAdapterModeCountEx(p,a,b) +#define IDirect3D9Ex_EnumAdapterModesEx(p,a,b,c,d) (p)->lpVtbl->EnumAdapterModesEx(p,a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayModeEx(p,a,b,c) (p)->lpVtbl->GetAdapterDisplayModeEx(p,a,b,c) +#define IDirect3D9Ex_CreateDeviceEx(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d,e,f,g) +#define IDirect3D9Ex_GetAdapterLUID(p,a,b) (p)->lpVtbl->GetAdapterLUID(p,a,b) +#else +/*** IUnknown methods ***/ +#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3D9Ex_AddRef(p) (p)->AddRef() +#define IDirect3D9Ex_Release(p) (p)->Release() +/*** IDirect3D9 methods ***/ +#define IDirect3D9Ex_RegisterSoftwareDevice(p,a) (p)->RegisterSoftwareDevice(a) +#define IDirect3D9Ex_GetAdapterCount(p) (p)->GetAdapterCount() +#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c) (p)->GetAdapterIdentifier(a,b,c) +#define IDirect3D9Ex_GetAdapterModeCount(p,a,b) (p)->GetAdapterModeCount(a,b) +#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d) (p)->EnumAdapterModes(a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b) (p)->GetAdapterDisplayMode(a,b) +#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e) (p)->CheckDeviceType(a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->CheckDeviceFormat(a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->CheckDeviceMultiSampleType(a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->CheckDepthStencilMatch(a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d) (p)->CheckDeviceFormatConversion(a,b,c,d) +#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c) (p)->GetDeviceCaps(a,b,c) +#define IDirect3D9Ex_GetAdapterMonitor(p,a) (p)->GetAdapterMonitor(a) +#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f) (p)->CreateDevice(a,b,c,d,e,f) +#endif + /***************************************************************************** * IDirect3DVolume9 interface */ @@ -1493,6 +1581,431 @@ DECLARE_INTERFACE_(IDirect3DDevice9,IUnknown) #endif +/***************************************************************************** + * IDirect3DDevice9Ex interface + */ +#define INTERFACE IDirect3DDevice9Ex +DECLARE_INTERFACE_(IDirect3DDevice9Ex,IDirect3DDevice9) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirect3DDevice9 methods ***/ + STDMETHOD(TestCooperativeLevel)(THIS) PURE; + STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE; + STDMETHOD(EvictManagedResources)(THIS) PURE; + STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE; + STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE; + STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) PURE; + STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y, DWORD Flags) PURE; + STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE; + STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE; + STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE; + STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) PURE; + STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE; + STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) PURE; + STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain, D3DGAMMARAMP* pRamp) PURE; + STDMETHOD(CreateTexture)(THIS_ UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateRenderTarget)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE; + STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) PURE; + STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) PURE; + STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain, IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) PURE; + STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) PURE; + STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE; + STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) PURE; + STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) PURE; + STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE; + STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE; + STDMETHOD(BeginScene)(THIS) PURE; + STDMETHOD(EndScene)(THIS) PURE; + STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) PURE; + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) PURE; + STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) PURE; + STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE, CONST D3DMATRIX*) PURE; + STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9*) PURE; + STDMETHOD(GetLight)(THIS_ DWORD Index, D3DLIGHT9*) PURE; + STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) PURE; + STDMETHOD(GetLightEnable)(THIS_ DWORD Index, BOOL* pEnable) PURE; + STDMETHOD(SetClipPlane)(THIS_ DWORD Index, CONST float* pPlane) PURE; + STDMETHOD(GetClipPlane)(THIS_ DWORD Index, float* pPlane) PURE; + STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) PURE; + STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD* pValue) PURE; + STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(BeginStateBlock)(THIS) PURE; + STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9** ppTexture) PURE; + STDMETHOD(SetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9* pTexture) PURE; + STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) PURE; + STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) PURE; + STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) PURE; + STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) PURE; + STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE; + STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber, CONST PALETTEENTRY* pEntries) PURE; + STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE; + STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE; + STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE; + STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE; + STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE; + STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE; + STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE; + STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE; + STDMETHOD_(float, GetNPatchMode)(THIS) PURE; + STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) PURE; + STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) PURE; + STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE; + STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE; + STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) PURE; + STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) PURE; + STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE; + STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE; + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE; + STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE; + STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE; + STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE; + STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE; + STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount) PURE; + STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE; + STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) PURE; + STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) PURE; + STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT Divider) PURE; + STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT* Divider) PURE; + STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE; + STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE; + STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE; + STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE; + STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE; + STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE; + STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE; + STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount) PURE; + STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE; + STDMETHOD(DrawRectPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE; + STDMETHOD(DrawTriPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE; + STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE; + STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) PURE; + /* IDirect3DDevice9Ex methods */ + STDMETHOD(SetConvolutionMonoKernel)(THIS_ UINT width, UINT height, float *rows, float *columns) PURE; + STDMETHOD(ComposeRects)(THIS_ IDirect3DSurface9 *pSrc, IDirect3DDevice9 *pDst, IDirect3DVertexBuffer9 *pSrcRectDescs, UINT NumRects, IDirect3DVertexBuffer9 *pDstRectDescs, D3DCOMPOSERECTSOP Operation, int Xoffset, int Yoffset) PURE; + STDMETHOD(PresentEx)(THIS_ CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) PURE; + STDMETHOD(GetGPUThreadPriority)(THIS_ INT *pPriority) PURE; + STDMETHOD(SetGPUThreadPriority)(THIS_ INT Priority) PURE; + STDMETHOD(WaitForVBlank)(THIS_ UINT iSwapChain) PURE; + STDMETHOD(CheckresourceResidency)(THIS_ IDirect3DResource9 ** pResourceArray, UINT32 Numresources) PURE; + STDMETHOD(SetMaximumFrameLatency)(THIS_ UINT MaxLatency) PURE; + STDMETHOD(GetMaximumFrameLatency)(THIS_ UINT *pMaxLatenxy) PURE; + STDMETHOD(CheckdeviceState)(THIS_ HWND hDestinationWindow) PURE; + STDMETHOD(CreateRenderTargetEx)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Lockable, IDirect3DSurface9 ** ppSurface, HANDLE *pSharedHandle, DWORD Usage) PURE; + STDMETHOD(CreateOffscreenPlainSurfaceEx)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) PURE; + STDMETHOD(CreateDepthStencilSurfaceEx)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurfface, HANDLE *pSharedHandle, DWORD Usage) PURE; + STDMETHOD(ResetEx)(THIS_ D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) PURE; + STDMETHOD(GetDisplayModeEx)(THIS_ UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DDevice9Ex_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DDevice9Ex_Release(p) (p)->lpVtbl->Release(p) +/*** IDirect3DDevice9 methods ***/ +#define IDirect3DDevice9Ex_TestCooperativeLevel(p) (p)->lpVtbl->TestCooperativeLevel(p) +#define IDirect3DDevice9Ex_GetAvailableTextureMem(p) (p)->lpVtbl->GetAvailableTextureMem(p) +#define IDirect3DDevice9Ex_EvictManagedResources(p) (p)->lpVtbl->EvictManagedResources(p) +#define IDirect3DDevice9Ex_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a) +#define IDirect3DDevice9Ex_GetDeviceCaps(p,a) (p)->lpVtbl->GetDeviceCaps(p,a) +#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b) (p)->lpVtbl->GetDisplayMode(p,a,b) +#define IDirect3DDevice9Ex_GetCreationParameters(p,a) (p)->lpVtbl->GetCreationParameters(p,a) +#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c) (p)->lpVtbl->SetCursorProperties(p,a,b,c) +#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c) (p)->lpVtbl->SetCursorPosition(p,a,b,c) +#define IDirect3DDevice9Ex_ShowCursor(p,a) (p)->lpVtbl->ShowCursor(p,a) +#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b) +#define IDirect3DDevice9Ex_GetSwapChain(p,a,b) (p)->lpVtbl->GetSwapChain(p,a,b) +#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p) (p)->lpVtbl->GetNumberOfSwapChains(p) +#define IDirect3DDevice9Ex_Reset(p,a) (p)->lpVtbl->Reset(p,a) +#define IDirect3DDevice9Ex_Present(p,a,b,c,d) (p)->lpVtbl->Present(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d) (p)->lpVtbl->GetBackBuffer(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b) (p)->lpVtbl->GetRasterStatus(p,a,b) +#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a) (p)->lpVtbl->SetDialogBoxMode(p,a) +#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c) (p)->lpVtbl->SetGammaRamp(p,a,b,c) +#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b) (p)->lpVtbl->GetGammaRamp(p,a,b) +#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d) (p)->lpVtbl->UpdateSurface(p,a,b,c,d) +#define IDirect3DDevice9Ex_UpdateTexture(p,a,b) (p)->lpVtbl->UpdateTexture(p,a,b) +#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b) (p)->lpVtbl->GetRenderTargetData(p,a,b) +#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b) +#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e) (p)->lpVtbl->StretchRect(p,a,b,c,d,e) +#define IDirect3DDevice9Ex_ColorFill(p,a,b,c) (p)->lpVtbl->ColorFill(p,a,b,c) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->lpVtbl->CreateOffscreenPlainSurface(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b) +#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b) (p)->lpVtbl->GetRenderTarget(p,a,b) +#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a) (p)->lpVtbl->SetDepthStencilSurface(p,a) +#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a) (p)->lpVtbl->GetDepthStencilSurface(p,a) +#define IDirect3DDevice9Ex_BeginScene(p) (p)->lpVtbl->BeginScene(p) +#define IDirect3DDevice9Ex_EndScene(p) (p)->lpVtbl->EndScene(p) +#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f) (p)->lpVtbl->Clear(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b) +#define IDirect3DDevice9Ex_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b) +#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b) +#define IDirect3DDevice9Ex_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a) +#define IDirect3DDevice9Ex_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a) +#define IDirect3DDevice9Ex_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a) +#define IDirect3DDevice9Ex_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a) +#define IDirect3DDevice9Ex_SetLight(p,a,b) (p)->lpVtbl->SetLight(p,a,b) +#define IDirect3DDevice9Ex_GetLight(p,a,b) (p)->lpVtbl->GetLight(p,a,b) +#define IDirect3DDevice9Ex_LightEnable(p,a,b) (p)->lpVtbl->LightEnable(p,a,b) +#define IDirect3DDevice9Ex_GetLightEnable(p,a,b) (p)->lpVtbl->GetLightEnable(p,a,b) +#define IDirect3DDevice9Ex_SetClipPlane(p,a,b) (p)->lpVtbl->SetClipPlane(p,a,b) +#define IDirect3DDevice9Ex_GetClipPlane(p,a,b) (p)->lpVtbl->GetClipPlane(p,a,b) +#define IDirect3DDevice9Ex_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b) +#define IDirect3DDevice9Ex_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b) +#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b) (p)->lpVtbl->CreateStateBlock(p,a,b) +#define IDirect3DDevice9Ex_BeginStateBlock(p) (p)->lpVtbl->BeginStateBlock(p) +#define IDirect3DDevice9Ex_EndStateBlock(p,a) (p)->lpVtbl->EndStateBlock(p,a) +#define IDirect3DDevice9Ex_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a) +#define IDirect3DDevice9Ex_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a) +#define IDirect3DDevice9Ex_GetTexture(p,a,b) (p)->lpVtbl->GetTexture(p,a,b) +#define IDirect3DDevice9Ex_SetTexture(p,a,b) (p)->lpVtbl->SetTexture(p,a,b) +#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c) +#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c) +#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c) (p)->lpVtbl->GetSamplerState(p,a,b,c) +#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c) (p)->lpVtbl->SetSamplerState(p,a,b,c) +#define IDirect3DDevice9Ex_ValidateDevice(p,a) (p)->lpVtbl->ValidateDevice(p,a) +#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b) (p)->lpVtbl->SetPaletteEntries(p,a,b) +#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b) (p)->lpVtbl->GetPaletteEntries(p,a,b) +#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a) (p)->lpVtbl->SetCurrentTexturePalette(p,a) +#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a) (p)->lpVtbl->GetCurrentTexturePalette(p,a) +#define IDirect3DDevice9Ex_SetScissorRect(p,a) (p)->lpVtbl->SetScissorRect(p,a) +#define IDirect3DDevice9Ex_GetScissorRect(p,a) (p)->lpVtbl->GetScissorRect(p,a) +#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a) (p)->lpVtbl->SetSoftwareVertexProcessing(p,a) +#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p) (p)->lpVtbl->GetSoftwareVertexProcessing(p) +#define IDirect3DDevice9Ex_SetNPatchMode(p,a) (p)->lpVtbl->SetNPatchMode(p,a) +#define IDirect3DDevice9Ex_GetNPatchMode(p) (p)->lpVtbl->GetNPatchMode(p) +#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c) (p)->lpVtbl->DrawPrimitive(p,a,b,c) +#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d) (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d) +#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f) (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b) (p)->lpVtbl->CreateVertexDeclaration(p,a,b) +#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a) (p)->lpVtbl->SetVertexDeclaration(p,a) +#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a) (p)->lpVtbl->GetVertexDeclaration(p,a) +#define IDirect3DDevice9Ex_SetFVF(p,a) (p)->lpVtbl->SetFVF(p,a) +#define IDirect3DDevice9Ex_GetFVF(p,a) (p)->lpVtbl->GetFVF(p,a) +#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b) (p)->lpVtbl->CreateVertexShader(p,a,b) +#define IDirect3DDevice9Ex_SetVertexShader(p,a) (p)->lpVtbl->SetVertexShader(p,a) +#define IDirect3DDevice9Ex_GetVertexShader(p,a) (p)->lpVtbl->GetVertexShader(p,a) +#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d) (p)->lpVtbl->SetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d) (p)->lpVtbl->GetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b) (p)->lpVtbl->SetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b) (p)->lpVtbl->GetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9Ex_SetIndices(p,a) (p)->lpVtbl->SetIndices(p,a) +#define IDirect3DDevice9Ex_GetIndices(p,a) (p)->lpVtbl->GetIndices(p,a) +#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b) (p)->lpVtbl->CreatePixelShader(p,a,b) +#define IDirect3DDevice9Ex_SetPixelShader(p,a) (p)->lpVtbl->SetPixelShader(p,a) +#define IDirect3DDevice9Ex_GetPixelShader(p,a) (p)->lpVtbl->GetPixelShader(p,a) +#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c) (p)->lpVtbl->DrawRectPatch(p,a,b,c) +#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c) (p)->lpVtbl->DrawTriPatch(p,a,b,c) +#define IDirect3DDevice9Ex_DeletePatch(p,a) (p)->lpVtbl->DeletePatch(p,a) +#define IDirect3DDevice9Ex_CreateQuery(p,a,b) (p)->lpVtbl->CreateQuery(p,a,b) +/* IDirect3DDevice9Ex */ +#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d) (p)->lpVtbl->SetConvolutionMonoKernel(p,a,b,c,d) +#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->ComposeRects(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e) (p)->lpVtbl->PresentEx(p,a,b,c,d,e) +#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a) (p)->lpVtbl->GetGPUThreadPriority(p,a) +#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a) (p)->lpVtbl->SetGPUThreadPriority(p,a) +#define IDirect3DDevice9Ex_WaitForVBlank(p,a) (p)->lpVtbl->WaitForVBlank(p,a) +#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b) (p)->lpVtbl->CheckResourceResidency(p,a,b) +#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a) (p)->lpVtbl->SetMaximumFrameLatency(p,a) +#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a) (p)->lpVtbl->GetMaximumFrameLatency(p,a) +#define IDirect3DDevice9Ex_CheckDeviceState(p,a) (p)->lpVtbl->CheckDeviceState(p,a) +#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g)(p)->lpVtbl->CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i)(p)->lpVtbl->CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_ResetEx(p,a,b) (p)->lpVtbl->ResetEx(p,a,b) +#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c) (p)->lpVtbl->GetDisplayModeEx(p,a,b,c) +#else +/*** IUnknown methods ***/ +#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DDevice9Ex_AddRef(p) (p)->AddRef() +#define IDirect3DDevice9Ex_Release(p) (p)->Release() +/*** IDirect3DDevice9 methods ***/ +#define IDirect3DDevice9Ex_TestCooperativeLevel(p) (p)->TestCooperativeLevel() +#define IDirect3DDevice9Ex_GetAvailableTextureMem(p) (p)->GetAvailableTextureMem() +#define IDirect3DDevice9Ex_EvictManagedResources(p) (p)->EvictManagedResources() +#define IDirect3DDevice9Ex_GetDirect3D(p,a) (p)->GetDirect3D(a) +#define IDirect3DDevice9Ex_GetDeviceCaps(p,a) (p)->GetDeviceCaps(a) +#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b) (p)->GetDisplayMode(a,b) +#define IDirect3DDevice9Ex_GetCreationParameters(p,a) (p)->GetCreationParameters(a) +#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c) (p)->SetCursorProperties(a,b,c) +#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c) (p)->SetCursorPosition(a,b,c) +#define IDirect3DDevice9Ex_ShowCursor(p,a) (p)->ShowCursor(a) +#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b) (p)->CreateAdditionalSwapChain(a,b) +#define IDirect3DDevice9Ex_GetSwapChain(p,a,b) (p)->GetSwapChain(a,b) +#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p) (p)->GetNumberOfSwapChains() +#define IDirect3DDevice9Ex_Reset(p,a) (p)->Reset(a) +#define IDirect3DDevice9Ex_Present(p,a,b,c,d) (p)->Present(a,b,c,d) +#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d) (p)->GetBackBuffer(a,b,c,d) +#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b) (p)->GetRasterStatus(a,b) +#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a) (p)->SetDialogBoxMode(a) +#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c) (p)->SetGammaRamp(a,b,c) +#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b) (p)->GetGammaRamp(a,b) +#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->CreateTexture(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->CreateCubeTexture(a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->CreateVertexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->CreateIndexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->CreateRenderTarget(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->CreateDepthStencilSurface(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d) (p)->UpdateSurface(a,b,c,d) +#define IDirect3DDevice9Ex_UpdateTexture(p,a,b) (p)->UpdateTexture(a,b) +#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b) (p)->GetRenderTargetData(a,b) +#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b) (p)->GetFrontBufferData(a,b) +#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e) (p)->StretchRect(a,b,c,d,e) +#define IDirect3DDevice9Ex_ColorFill(p,a,b,c) (p)->ColorFill(a,b,c) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->CreateOffscreenPlainSurface(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b) +#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b) (p)->GetRenderTarget(a,b) +#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a) (p)->SetDepthStencilSurface(a) +#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a) (p)->GetDepthStencilSurface(a) +#define IDirect3DDevice9Ex_BeginScene(p) (p)->BeginScene() +#define IDirect3DDevice9Ex_EndScene(p) (p)->EndScene() +#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f) (p)->Clear(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetTransform(p,a,b) (p)->SetTransform(a,b) +#define IDirect3DDevice9Ex_GetTransform(p,a,b) (p)->GetTransform(a,b) +#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b) +#define IDirect3DDevice9Ex_SetViewport(p,a) (p)->SetViewport(a) +#define IDirect3DDevice9Ex_GetViewport(p,a) (p)->GetViewport(a) +#define IDirect3DDevice9Ex_SetMaterial(p,a) (p)->SetMaterial(a) +#define IDirect3DDevice9Ex_GetMaterial(p,a) (p)->GetMaterial(a) +#define IDirect3DDevice9Ex_SetLight(p,a,b) (p)->SetLight(a,b) +#define IDirect3DDevice9Ex_GetLight(p,a,b) (p)->GetLight(a,b) +#define IDirect3DDevice9Ex_LightEnable(p,a,b) (p)->LightEnable(a,b) +#define IDirect3DDevice9Ex_GetLightEnable(p,a,b) (p)->GetLightEnable(a,b) +#define IDirect3DDevice9Ex_SetClipPlane(p,a,b) (p)->SetClipPlane(a,b) +#define IDirect3DDevice9Ex_GetClipPlane(p,a,b) (p)->GetClipPlane(a,b) +#define IDirect3DDevice9Ex_SetRenderState(p,a,b) (p)->SetRenderState(a,b) +#define IDirect3DDevice9Ex_GetRenderState(p,a,b) (p)->GetRenderState(a,b) +#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b) (p)->CreateStateBlock(a,b) +#define IDirect3DDevice9Ex_BeginStateBlock(p) (p)->BeginStateBlock() +#define IDirect3DDevice9Ex_EndStateBlock(p,a) (p)->EndStateBlock(a) +#define IDirect3DDevice9Ex_SetClipStatus(p,a) (p)->SetClipStatus(a) +#define IDirect3DDevice9Ex_GetClipStatus(p,a) (p)->GetClipStatus(a) +#define IDirect3DDevice9Ex_GetTexture(p,a,b) (p)->GetTexture(a,b) +#define IDirect3DDevice9Ex_SetTexture(p,a,b) (p)->SetTexture(a,b) +#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c) (p)->GetTextureStageState(a,b,c) +#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c) (p)->SetTextureStageState(a,b,c) +#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c) (p)->GetSamplerState(a,b,c) +#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c) (p)->SetSamplerState(a,b,c) +#define IDirect3DDevice9Ex_ValidateDevice(p,a) (p)->ValidateDevice(a) +#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b) (p)->SetPaletteEntries(a,b) +#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b) (p)->GetPaletteEntries(a,b) +#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a) (p)->SetCurrentTexturePalette(a) +#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a) (p)->GetCurrentTexturePalette(a) +#define IDirect3DDevice9Ex_SetScissorRect(p,a) (p)->SetScissorRect(a) +#define IDirect3DDevice9Ex_GetScissorRect(p,a) (p)->GetScissorRect(a) +#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a) (p)->SetSoftwareVertexProcessing(a) +#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p) (p)->GetSoftwareVertexProcessing() +#define IDirect3DDevice9Ex_SetNPatchMode(p,a) (p)->SetNPatchMode(a) +#define IDirect3DDevice9Ex_GetNPatchMode(p) (p)->GetNPatchMode() +#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c) (p)->DrawPrimitive(a,b,c) +#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->DrawIndexedPrimitive(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d) (p)->DrawPrimitiveUP(a,b,c,d) +#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f) (p)->ProcessVertices(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b) (p)->CreateVertexDeclaration(a,b) +#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a) (p)->SetVertexDeclaration(a) +#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a) (p)->GetVertexDeclaration(a) +#define IDirect3DDevice9Ex_SetFVF(p,a) (p)->SetFVF(a) +#define IDirect3DDevice9Ex_GetFVF(p,a) (p)->GetFVF(a) +#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b) (p)->CreateVertexShader(a,b) +#define IDirect3DDevice9Ex_SetVertexShader(p,a) (p)->SetVertexShader(a) +#define IDirect3DDevice9Ex_GetVertexShader(p,a) (p)->GetVertexShader(a) +#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c) (p)->SetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c) (p)->GetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c) (p)->SetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c) (p)->GetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c) (p)->SetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c) (p)->GetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d) (p)->SetStreamSource(a,b,c,d) +#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d) (p)->GetStreamSource(a,b,c,d) +#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b) (p)->SetStreamSourceFreq(a,b) +#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b) (p)->GetStreamSourceFreq(a,b) +#define IDirect3DDevice9Ex_SetIndices(p,a) (p)->SetIndices(a) +#define IDirect3DDevice9Ex_GetIndices(p,a) (p)->GetIndices(a) +#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b) (p)->CreatePixelShader(a,b) +#define IDirect3DDevice9Ex_SetPixelShader(p,a) (p)->SetPixelShader(a) +#define IDirect3DDevice9Ex_GetPixelShader(p,a) (p)->GetPixelShader(a) +#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c) (p)->SetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c) (p)->GetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c) (p)->SetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c) (p)->GetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c) (p)->SetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c) (p)->GetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c) (p)->DrawRectPatch(a,b,c) +#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c) (p)->DrawTriPatch(a,b,c) +#define IDirect3DDevice9Ex_DeletePatch(p,a) (p)->DeletePatch(a) +#define IDirect3DDevice9Ex_CreateQuery(p,a,b) (p)->CreateQuery(a,b) +/* IDirect3DDevice9Ex */ +#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d) (p)->SetConvolutionMonoKernel(a,b,c,d) +#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h) (p)->ComposeRects(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e) (p)->PresentEx(a,b,c,d,e) +#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a) (p)->GetGPUThreadPriority(a) +#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a) (p)->SetGPUThreadPriority(a) +#define IDirect3DDevice9Ex_WaitForVBlank(p,a) (p)->WaitForVBlank(a) +#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b) (p)->CheckResourceResidency(a,b) +#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a) (p)->SetMaximumFrameLatency(a) +#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a) (p)->GetMaximumFrameLatency(a) +#define IDirect3DDevice9Ex_CheckDeviceState(p,a) (p)->CheckDeviceState(a) +#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) (p)->CreateRenderTargetEx(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g)(p)->CreateOffscreenPlainSurfaceEx(a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i)(p)->CreateDepthStencilSurfaceEx(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_ResetEx(p,a,b) (p)->ResetEx(a,b) +#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c) (p)->GetDisplayModeEx(a,b,c) +#endif + + #ifdef __cplusplus extern "C" { #endif /* defined(__cplusplus) */ diff --git a/reactos/include/psdk/d3d9types.h b/reactos/include/psdk/d3d9types.h index 2d4267e1ce0..ba800bf18d6 100644 --- a/reactos/include/psdk/d3d9types.h +++ b/reactos/include/psdk/d3d9types.h @@ -1541,6 +1541,49 @@ typedef struct _D3DVOLUME_DESC { UINT Depth; } D3DVOLUME_DESC; +#if !defined(D3D_DISABLE_9EX) +typedef enum D3DSCANLINEORDERING +{ + D3DSCANLINEORDERING_UNKNOWN, + D3DSCANLINEORDERING_PROGRESSIVE, + D3DSCANLINEORDERING_INTERLACED, +} D3DSCANLINEORDERING; + + +typedef struct D3DDISPLAYMODEFILTER +{ + UINT Size; + D3DFORMAT Format; + D3DSCANLINEORDERING ScanLineOrdering; +} D3DDISPLAYMODEFILTER; + +typedef struct D3DDISPLAYMODEEX +{ + UINT Size; + UINT Width; + UINT Height; + UINT RefreshRate; + D3DFORMAT Format; + D3DSCANLINEORDERING ScanLineOrdering; +} D3DDISPLAYMODEEX; + +typedef enum D3DDISPLAYROTATION +{ + D3DDISPLAYROTATION_IDENTITY = 1, + D3DDISPLAYROTATION_90, + D3DDISPLAYROTATION_180, + D3DDISPLAYROTATION_270 +} D3DDISPLAYROTATION; + +typedef enum _D3DCOMPOSERECTSOP{ + D3DCOMPOSERECTS_COPY = 1, + D3DCOMPOSERECTS_OR, + D3DCOMPOSERECTS_AND, + D3DCOMPOSERECTS_NEG, + D3DCOMPOSERECTS_FORCE_DWORD = 0x7fffffff +} D3DCOMPOSERECTSOP; +#endif /* D3D_DISABLE_9EX */ + #pragma pack(pop) #endif /* __WINE_D3D9TYPES_H */ diff --git a/reactos/include/reactos/wine/wined3d_caps.h b/reactos/include/reactos/wine/wined3d_caps.h index 95b400e4eef..1cfbbd49bf5 100644 --- a/reactos/include/reactos/wine/wined3d_caps.h +++ b/reactos/include/reactos/wine/wined3d_caps.h @@ -53,6 +53,7 @@ #define WINED3DLINECAPS_BLEND 0x00000004 #define WINED3DLINECAPS_ALPHACMP 0x00000008 #define WINED3DLINECAPS_FOG 0x00000010 +#define WINED3DLINECAPS_ANTIALIAS 0x00000020 #define WINED3DMAX30SHADERINSTRUCTIONS 32768 #define WINED3DMIN30SHADERINSTRUCTIONS 512 @@ -168,4 +169,144 @@ #define WINED3DVS20CAPS_PREDICATION 0x00000001 +/* DirectDraw Caps */ +#define WINEDDSCAPS_RESERVED1 0x00000001 +#define WINEDDSCAPS_ALPHA 0x00000002 +#define WINEDDSCAPS_BACKBUFFER 0x00000004 +#define WINEDDSCAPS_COMPLEX 0x00000008 +#define WINEDDSCAPS_FLIP 0x00000010 +#define WINEDDSCAPS_FRONTBUFFER 0x00000020 +#define WINEDDSCAPS_OFFSCREENPLAIN 0x00000040 +#define WINEDDSCAPS_OVERLAY 0x00000080 +#define WINEDDSCAPS_PALETTE 0x00000100 +#define WINEDDSCAPS_PRIMARYSURFACE 0x00000200 +#define WINEDDSCAPS_PRIMARYSURFACELEFT 0x00000400 +#define WINEDDSCAPS_SYSTEMMEMORY 0x00000800 +#define WINEDDSCAPS_TEXTURE 0x00001000 +#define WINEDDSCAPS_3DDEVICE 0x00002000 +#define WINEDDSCAPS_VIDEOMEMORY 0x00004000 +#define WINEDDSCAPS_VISIBLE 0x00008000 +#define WINEDDSCAPS_WRITEONLY 0x00010000 +#define WINEDDSCAPS_ZBUFFER 0x00020000 +#define WINEDDSCAPS_OWNDC 0x00040000 +#define WINEDDSCAPS_LIVEVIDEO 0x00080000 +#define WINEDDSCAPS_HWCODEC 0x00100000 +#define WINEDDSCAPS_MODEX 0x00200000 +#define WINEDDSCAPS_MIPMAP 0x00400000 +#define WINEDDSCAPS_RESERVED2 0x00800000 +#define WINEDDSCAPS_ALLOCONLOAD 0x04000000 +#define WINEDDSCAPS_VIDEOPORT 0x08000000 +#define WINEDDSCAPS_LOCALVIDMEM 0x10000000 +#define WINEDDSCAPS_NONLOCALVIDMEM 0x20000000 +#define WINEDDSCAPS_STANDARDVGAMODE 0x40000000 +#define WINEDDSCAPS_OPTIMIZED 0x80000000 + +#define WINEDDCKEYCAPS_DESTBLT 0x00000001 +#define WINEDDCKEYCAPS_DESTBLTCLRSPACE 0x00000002 +#define WINEDDCKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004 +#define WINEDDCKEYCAPS_DESTBLTYUV 0x00000008 +#define WINEDDCKEYCAPS_DESTOVERLAY 0x00000010 +#define WINEDDCKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020 +#define WINEDDCKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040 +#define WINEDDCKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080 +#define WINEDDCKEYCAPS_DESTOVERLAYYUV 0x00000100 +#define WINEDDCKEYCAPS_SRCBLT 0x00000200 +#define WINEDDCKEYCAPS_SRCBLTCLRSPACE 0x00000400 +#define WINEDDCKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800 +#define WINEDDCKEYCAPS_SRCBLTYUV 0x00001000 +#define WINEDDCKEYCAPS_SRCOVERLAY 0x00002000 +#define WINEDDCKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000 +#define WINEDDCKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000 +#define WINEDDCKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000 +#define WINEDDCKEYCAPS_SRCOVERLAYYUV 0x00020000 +#define WINEDDCKEYCAPS_NOCOSTOVERLAY 0x00040000 + +#define WINEDDFXCAPS_BLTALPHA 0x00000001 +#define WINEDDFXCAPS_OVERLAYALPHA 0x00000004 +#define WINEDDFXCAPS_BLTARITHSTRETCHYN 0x00000010 +#define WINEDDFXCAPS_BLTARITHSTRETCHY 0x00000020 +#define WINEDDFXCAPS_BLTMIRRORLEFTRIGHT 0x00000040 +#define WINEDDFXCAPS_BLTMIRRORUPDOWN 0x00000080 +#define WINEDDFXCAPS_BLTROTATION 0x00000100 +#define WINEDDFXCAPS_BLTROTATION90 0x00000200 +#define WINEDDFXCAPS_BLTSHRINKX 0x00000400 +#define WINEDDFXCAPS_BLTSHRINKXN 0x00000800 +#define WINEDDFXCAPS_BLTSHRINKY 0x00001000 +#define WINEDDFXCAPS_BLTSHRINKYN 0x00002000 +#define WINEDDFXCAPS_BLTSTRETCHX 0x00004000 +#define WINEDDFXCAPS_BLTSTRETCHXN 0x00008000 +#define WINEDDFXCAPS_BLTSTRETCHY 0x00010000 +#define WINEDDFXCAPS_BLTSTRETCHYN 0x00020000 +#define WINEDDFXCAPS_OVERLAYARITHSTRETCHY 0x00040000 +#define WINEDDFXCAPS_OVERLAYARITHSTRETCHYN 0x00000008 +#define WINEDDFXCAPS_OVERLAYSHRINKX 0x00080000 +#define WINEDDFXCAPS_OVERLAYSHRINKXN 0x00100000 +#define WINEDDFXCAPS_OVERLAYSHRINKY 0x00200000 +#define WINEDDFXCAPS_OVERLAYSHRINKYN 0x00400000 +#define WINEDDFXCAPS_OVERLAYSTRETCHX 0x00800000 +#define WINEDDFXCAPS_OVERLAYSTRETCHXN 0x01000000 +#define WINEDDFXCAPS_OVERLAYSTRETCHY 0x02000000 +#define WINEDDFXCAPS_OVERLAYSTRETCHYN 0x04000000 +#define WINEDDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000 +#define WINEDDFXCAPS_OVERLAYMIRRORUPDOWN 0x10000000 + +#define WINEDDCAPS_3D 0x00000001 +#define WINEDDCAPS_ALIGNBOUNDARYDEST 0x00000002 +#define WINEDDCAPS_ALIGNSIZEDEST 0x00000004 +#define WINEDDCAPS_ALIGNBOUNDARYSRC 0x00000008 +#define WINEDDCAPS_ALIGNSIZESRC 0x00000010 +#define WINEDDCAPS_ALIGNSTRIDE 0x00000020 +#define WINEDDCAPS_BLT 0x00000040 +#define WINEDDCAPS_BLTQUEUE 0x00000080 +#define WINEDDCAPS_BLTFOURCC 0x00000100 +#define WINEDDCAPS_BLTSTRETCH 0x00000200 +#define WINEDDCAPS_GDI 0x00000400 +#define WINEDDCAPS_OVERLAY 0x00000800 +#define WINEDDCAPS_OVERLAYCANTCLIP 0x00001000 +#define WINEDDCAPS_OVERLAYFOURCC 0x00002000 +#define WINEDDCAPS_OVERLAYSTRETCH 0x00004000 +#define WINEDDCAPS_PALETTE 0x00008000 +#define WINEDDCAPS_PALETTEVSYNC 0x00010000 +#define WINEDDCAPS_READSCANLINE 0x00020000 +#define WINEDDCAPS_STEREOVIEW 0x00040000 +#define WINEDDCAPS_VBI 0x00080000 +#define WINEDDCAPS_ZBLTS 0x00100000 +#define WINEDDCAPS_ZOVERLAYS 0x00200000 +#define WINEDDCAPS_COLORKEY 0x00400000 +#define WINEDDCAPS_ALPHA 0x00800000 +#define WINEDDCAPS_COLORKEYHWASSIST 0x01000000 +#define WINEDDCAPS_NOHARDWARE 0x02000000 +#define WINEDDCAPS_BLTCOLORFILL 0x04000000 +#define WINEDDCAPS_BANKSWITCHED 0x08000000 +#define WINEDDCAPS_BLTDEPTHFILL 0x10000000 +#define WINEDDCAPS_CANCLIP 0x20000000 +#define WINEDDCAPS_CANCLIPSTRETCHED 0x40000000 +#define WINEDDCAPS_CANBLTSYSMEM 0x80000000 + +#define WINEDDCAPS2_CERTIFIED 0x00000001 +#define WINEDDCAPS2_NO2DDURING3DSCENE 0x00000002 +#define WINEDDCAPS2_VIDEOPORT 0x00000004 +#define WINEDDCAPS2_AUTOFLIPOVERLAY 0x00000008 +#define WINEDDCAPS2_CANBOBINTERLEAVED 0x00000010 +#define WINEDDCAPS2_CANBOBNONINTERLEAVED 0x00000020 +#define WINEDDCAPS2_COLORCONTROLOVERLAY 0x00000040 +#define WINEDDCAPS2_COLORCONTROLPRIMARY 0x00000080 +#define WINEDDCAPS2_CANDROPZ16BIT 0x00000100 +#define WINEDDCAPS2_NONLOCALVIDMEM 0x00000200 +#define WINEDDCAPS2_NONLOCALVIDMEMCAPS 0x00000400 +#define WINEDDCAPS2_NOPAGELOCKREQUIRED 0x00000800 +#define WINEDDCAPS2_WIDESURFACES 0x00001000 +#define WINEDDCAPS2_CANFLIPODDEVEN 0x00002000 +#define WINEDDCAPS2_CANBOBHARDWARE 0x00004000 +#define WINEDDCAPS2_COPYFOURCC 0x00008000 +#define WINEDDCAPS2_PRIMARYGAMMA 0x00020000 +#define WINEDDCAPS2_CANRENDERWINDOWED 0x00080000 +#define WINEDDCAPS2_CANCALIBRATEGAMMA 0x00100000 +#define WINEDDCAPS2_FLIPINTERVAL 0x00200000 +#define WINEDDCAPS2_FLIPNOVSYNC 0x00400000 +#define WINEDDCAPS2_CANMANAGETEXTURE 0x00800000 +#define WINEDDCAPS2_TEXMANINNONLOCALVIDMEM 0x01000000 +#define WINEDDCAPS2_STEREO 0x02000000 +#define WINEDDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL 0x04000000 + #endif /* __WINE_WINED3D_CAPS_H */ diff --git a/reactos/include/reactos/wine/wined3d_gl.h b/reactos/include/reactos/wine/wined3d_gl.h index b3460640d6d..3101c17ba4a 100644 --- a/reactos/include/reactos/wine/wined3d_gl.h +++ b/reactos/include/reactos/wine/wined3d_gl.h @@ -803,7 +803,7 @@ typedef void GLvoid; void (WINE_GLAPI *glAccum) (GLenum op, GLfloat value); void (WINE_GLAPI *glAlphaFunc) (GLenum func, GLclampf ref); -GLboolean (WINE_GLAPI *glAreTexturesResident) (GLsizei n, const GLuint* textures, const GLboolean* residences); +GLboolean (WINE_GLAPI *glAreTexturesResident) (GLsizei n, const GLuint* textures, GLboolean* residences); void (WINE_GLAPI *glArrayElement) (GLint i); void (WINE_GLAPI *glBegin) (GLenum mode); void (WINE_GLAPI *glBindTexture) (GLenum target, GLuint texture); @@ -889,9 +889,7 @@ void (WINE_GLAPI *glEvalMesh1) (GLenum mode, GLint i1, GLint i2); void (WINE_GLAPI *glEvalMesh2) (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); void (WINE_GLAPI *glEvalPoint1) (GLint i); void (WINE_GLAPI *glEvalPoint2) (GLint i, GLint j); -void (WINE_GLAPI *glFeedbackBuffer) (GLsizei size, GLenum type, const GLfloat* buffer); -void (WINE_GLAPI *glFinish) (); -void (WINE_GLAPI *glFlush) (); +void (WINE_GLAPI *glFeedbackBuffer) (GLsizei size, GLenum type, GLfloat* buffer); void (WINE_GLAPI *glFogf) (GLenum pname, GLfloat param); void (WINE_GLAPI *glFogfv) (GLenum pname, const GLfloat* params); void (WINE_GLAPI *glFogi) (GLenum pname, GLint param); @@ -899,36 +897,36 @@ void (WINE_GLAPI *glFogiv) (GLenum pname, const GLint* params); void (WINE_GLAPI *glFrontFace) (GLenum mode); void (WINE_GLAPI *glFrustum) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); GLuint (WINE_GLAPI *glGenLists) (GLsizei range); -void (WINE_GLAPI *glGenTextures) (GLsizei n, const GLuint* textures); -void (WINE_GLAPI *glGetBooleanv) (GLenum pname, const GLboolean* params); -void (WINE_GLAPI *glGetClipPlane) (GLenum plane, const GLdouble* equation); -void (WINE_GLAPI *glGetDoublev) (GLenum pname, const GLdouble* params); +void (WINE_GLAPI *glGenTextures) (GLsizei n, GLuint* textures); +void (WINE_GLAPI *glGetBooleanv) (GLenum pname, GLboolean* params); +void (WINE_GLAPI *glGetClipPlane) (GLenum plane, GLdouble* equation); +void (WINE_GLAPI *glGetDoublev) (GLenum pname, GLdouble* params); GLenum (WINE_GLAPI *glGetError) (); -void (WINE_GLAPI *glGetFloatv) (GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetIntegerv) (GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetLightfv) (GLenum light, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetLightiv) (GLenum light, GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetMapdv) (GLenum target, GLenum query, const GLdouble* v); -void (WINE_GLAPI *glGetMapfv) (GLenum target, GLenum query, const GLfloat* v); -void (WINE_GLAPI *glGetMapiv) (GLenum target, GLenum query, const GLint* v); -void (WINE_GLAPI *glGetMaterialfv) (GLenum face, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetMaterialiv) (GLenum face, GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetPixelMapfv) (GLenum map, const GLfloat* values); -void (WINE_GLAPI *glGetPixelMapuiv) (GLenum map, const GLuint* values); -void (WINE_GLAPI *glGetPixelMapusv) (GLenum map, const GLushort* values); -void (WINE_GLAPI *glGetPointerv) (GLenum pname, const GLvoid** params); -void (WINE_GLAPI *glGetPolygonStipple) (const GLubyte* mask); +void (WINE_GLAPI *glGetFloatv) (GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetIntegerv) (GLenum pname, GLint* params); +void (WINE_GLAPI *glGetLightfv) (GLenum light, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetLightiv) (GLenum light, GLenum pname, GLint* params); +void (WINE_GLAPI *glGetMapdv) (GLenum target, GLenum query, GLdouble* v); +void (WINE_GLAPI *glGetMapfv) (GLenum target, GLenum query, GLfloat* v); +void (WINE_GLAPI *glGetMapiv) (GLenum target, GLenum query, GLint* v); +void (WINE_GLAPI *glGetMaterialfv) (GLenum face, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetMaterialiv) (GLenum face, GLenum pname, GLint* params); +void (WINE_GLAPI *glGetPixelMapfv) (GLenum map, GLfloat* values); +void (WINE_GLAPI *glGetPixelMapuiv) (GLenum map, GLuint* values); +void (WINE_GLAPI *glGetPixelMapusv) (GLenum map, GLushort* values); +void (WINE_GLAPI *glGetPointerv) (GLenum pname, GLvoid** params); +void (WINE_GLAPI *glGetPolygonStipple) (GLubyte* mask); const GLubyte * (WINE_GLAPI *glGetString) (GLenum name); -void (WINE_GLAPI *glGetTexEnvfv) (GLenum target, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetTexEnviv) (GLenum target, GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetTexGendv) (GLenum coord, GLenum pname, const GLdouble* params); -void (WINE_GLAPI *glGetTexGenfv) (GLenum coord, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetTexGeniv) (GLenum coord, GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, const GLvoid* pixels); -void (WINE_GLAPI *glGetTexLevelParameterfv) (GLenum target, GLint level, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, const GLint* params); -void (WINE_GLAPI *glGetTexParameterfv) (GLenum target, GLenum pname, const GLfloat* params); -void (WINE_GLAPI *glGetTexParameteriv) (GLenum target, GLenum pname, const GLint* params); +void (WINE_GLAPI *glGetTexEnvfv) (GLenum target, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetTexEnviv) (GLenum target, GLenum pname, GLint* params); +void (WINE_GLAPI *glGetTexGendv) (GLenum coord, GLenum pname, GLdouble* params); +void (WINE_GLAPI *glGetTexGenfv) (GLenum coord, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetTexGeniv) (GLenum coord, GLenum pname, GLint* params); +void (WINE_GLAPI *glGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); +void (WINE_GLAPI *glGetTexLevelParameterfv) (GLenum target, GLint level, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint* params); +void (WINE_GLAPI *glGetTexParameterfv) (GLenum target, GLenum pname, GLfloat* params); +void (WINE_GLAPI *glGetTexParameteriv) (GLenum target, GLenum pname, GLint* params); void (WINE_GLAPI *glHint) (GLenum target, GLenum mode); void (WINE_GLAPI *glIndexMask) (GLuint mask); void (WINE_GLAPI *glIndexPointer) (GLenum type, GLsizei stride, const GLvoid* pointer); @@ -1038,7 +1036,7 @@ void (WINE_GLAPI *glRasterPos4iv) (const GLint* v); void (WINE_GLAPI *glRasterPos4s) (GLshort x, GLshort y, GLshort z, GLshort w); void (WINE_GLAPI *glRasterPos4sv) (const GLshort* v); void (WINE_GLAPI *glReadBuffer) (GLenum mode); -void (WINE_GLAPI *glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +void (WINE_GLAPI *glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); void (WINE_GLAPI *glRectd) (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); void (WINE_GLAPI *glRectdv) (const GLdouble* v1, const GLdouble* v2); void (WINE_GLAPI *glRectf) (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); @@ -1053,7 +1051,7 @@ void (WINE_GLAPI *glRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); void (WINE_GLAPI *glScaled) (GLdouble x, GLdouble y, GLdouble z); void (WINE_GLAPI *glScalef) (GLfloat x, GLfloat y, GLfloat z); void (WINE_GLAPI *glScissor) (GLint x, GLint y, GLsizei width, GLsizei height); -void (WINE_GLAPI *glSelectBuffer) (GLsizei size, const GLuint* buffer); +void (WINE_GLAPI *glSelectBuffer) (GLsizei size, GLuint* buffer); void (WINE_GLAPI *glShadeModel) (GLenum mode); void (WINE_GLAPI *glStencilFunc) (GLenum func, GLint ref, GLuint mask); void (WINE_GLAPI *glStencilMask) (GLuint mask); @@ -1139,6 +1137,12 @@ void (WINE_GLAPI *glVertexPointer) (GLint size, GLenum type, GLsizei stride, con void (WINE_GLAPI *glViewport) (GLint x, GLint y, GLsizei width, GLsizei height); void (WINE_GLAPI *glPointParameterfv) (GLenum pname, const GLfloat *params); +/* glFinish and glFlush are always loaded from opengl32.dll, thus they always have + * __stdcall calling convention + */ +void (__stdcall *glFinish) (); +void (__stdcall *glFlush) (); + /* WGL functions */ HGLRC (WINAPI *pwglCreateContext)(HDC); BOOL (WINAPI *pwglDeleteContext)(HGLRC); @@ -1238,8 +1242,6 @@ BOOL (WINAPI *pwglShareLists)(HGLRC,HGLRC); USE_GL_FUNC(glEvalPoint1) \ USE_GL_FUNC(glEvalPoint2) \ USE_GL_FUNC(glFeedbackBuffer) \ - USE_GL_FUNC(glFinish) \ - USE_GL_FUNC(glFlush) \ USE_GL_FUNC(glFogf) \ USE_GL_FUNC(glFogfv) \ USE_GL_FUNC(glFogi) \ @@ -1502,6 +1504,16 @@ BOOL (WINAPI *pwglShareLists)(HGLRC,HGLRC); * #defines and functions pointer ****************************************************/ +/* GL_ARB_color_buffer_float */ +#ifndef GL_ARB_color_buffer_float +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D +#endif +typedef void (WINE_GLAPI *PGLFNCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + /* GL_ARB_depth_texture */ #ifndef GL_ARB_depth_texture #define GL_ARB_depth_texture 1 @@ -2237,6 +2249,16 @@ typedef GLvoid* (WINE_GLAPI * PGLFNMAPBUFFERARBPROC) (GLenum target, GLenum acce typedef GLboolean (WINE_GLAPI * PGLFNUNMAPBUFFERARBPROC) (GLenum target); typedef void (WINE_GLAPI * PGLFNGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (WINE_GLAPI * PGLFNGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params); +/* GL_EXT_blend_equation_separate */ +typedef void (WINE_GLAPI * PGLFNBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +/* GL_EXT_blend_func_separate */ +#ifndef GL_EXT_blend_func_separate +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#endif +typedef void (WINE_GLAPI * PGLFNBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); /* GL_EXT_fog_coord */ #ifndef GL_EXT_fog_coord #define GL_EXT_fog_coord 1 @@ -2430,23 +2452,6 @@ typedef void (WINE_GLAPI * PGLFNGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint #define GL_INCR_WRAP_EXT 0x8507 #define GL_DECR_WRAP_EXT 0x8508 #endif -/* GL_EXT_vertex_weighting */ -#ifndef GL_EXT_vertex_weighting -#define GL_EXT_vertex_weighting 1 -#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH -#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 -#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX -#define GL_MODELVIEW1_MATRIX_EXT 0x8506 -#define GL_VERTEX_WEIGHTING_EXT 0x8509 -#define GL_MODELVIEW0_EXT GL_MODELVIEW -#define GL_MODELVIEW1_EXT 0x850A -#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B -#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C -#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D -#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E -#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F -#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 -#endif /* GL_NV_half_float */ #ifndef GL_NV_half_float @@ -2866,6 +2871,142 @@ typedef void (WINE_GLAPI * PGLFNFINISHRENDERAPPLEPROC) (void); #define UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB #endif +/* GL_ARB_texture_rectangle */ +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#endif + +/* GL_APPLE_float_pixels */ +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels +#define GL_HALF_APPLE 0x140B +#define GL_COLOR_FLOAT_APPLE 0x8A0F +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#endif + +/* GL_EXT_gpu_program_parameters */ +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters +typedef void (WINE_GLAPI * PGLFNPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const float *params); +typedef void (WINE_GLAPI * PGLFNPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const float *params); +#endif + +/* GL_NV_light_max_exponent */ +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +/* GL_ATI_fragment_shader */ +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader +typedef GLuint (WINE_GLAPI *PGLFNGENFRAGMENTSHADERSATI) (GLuint range); +typedef void (WINE_GLAPI *PGLFNBINDFRAGMENTSHADERATI) (GLuint id); +typedef void (WINE_GLAPI *PGLFNDELETEFRAGMENTSHADERATI) (GLuint id); +typedef void (WINE_GLAPI *PGLFNBEGINFRAGMENTSHADERATI) (); +typedef void (WINE_GLAPI *PGLFNENDFRAGMENTSHADERATI) (); +typedef void (WINE_GLAPI *PGLFNPASSTEXCOORDATI) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (WINE_GLAPI *PGLFNSAMPLEMAPATI) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (WINE_GLAPI *PGLFNCOLORFRAGMENTOP1ATI) (GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod); +typedef void (WINE_GLAPI *PGLFNCOLORFRAGMENTOP2ATI) (GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod); +typedef void (WINE_GLAPI *PGLFNCOLORFRAGMENTOP3ATI) (GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, + GLuint arg3Mod); +typedef void (WINE_GLAPI *PGLFNALPHAFRAGMENTOP1ATI) (GLenum op, GLuint dst, GLuint dstMod, + GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (WINE_GLAPI *PGLFNALPHAFRAGMENTOP2ATI) (GLenum op, GLuint dst, GLuint dstMod, + GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, + GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (WINE_GLAPI *PGLFNALPHAFRAGMENTOP3ATI) (GLenum op, GLuint dst, GLuint dstMod, + GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, + GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, + GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (WINE_GLAPI *PGLFNSETFRAGMENTSHADERCONSTANTATI) (GLuint dst, const GLfloat *value); +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_RED_BIT_ATI 0x00000001 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#endif +/* GL_ATI_texture_compression_3dc */ +#ifndef GL_ATI_texture_compression_3dc +#define GL_ATI_texture_compression_3dc +#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 +#endif +/* GL_EXT_texture_compression_rgtc */ +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#endif + /* GL_VERSION_2_0 */ #ifndef GL_VERSION_2_0 #define GL_VERSION_2_0 1 @@ -3086,6 +3227,7 @@ typedef enum _GL_Cards { CARD_ATI_RADEON_HD2300 = 0x7210, CARD_ATI_RADEON_HD2600 = 0x9581, CARD_ATI_RADEON_HD2900 = 0x9400, + CARD_ATI_RADEON_HD3200 = 0x9620, CARD_NVIDIA_RIVA_128 = 0x0018, CARD_NVIDIA_RIVA_TNT = 0x0020, @@ -3102,17 +3244,24 @@ typedef enum _GL_Cards { CARD_NVIDIA_GEFORCE_6200 = 0x014f, CARD_NVIDIA_GEFORCE_6600GT = 0x0140, CARD_NVIDIA_GEFORCE_6800 = 0x0041, + CARD_NVIDIA_GEFORCE_7400 = 0x01d8, + CARD_NVIDIA_GEFORCE_7300 = 0x01d7, /* GeForce Go 7300 */ + CARD_NVIDIA_GEFORCE_7600 = 0x0391, CARD_NVIDIA_GEFORCE_7800GT = 0x0092, CARD_NVIDIA_GEFORCE_8300GS = 0x0423, CARD_NVIDIA_GEFORCE_8600GT = 0x0402, + CARD_NVIDIA_GEFORCE_8600MGT = 0x0407, CARD_NVIDIA_GEFORCE_8800GTS = 0x0193, + CARD_NVIDIA_GEFORCE_9600GT = 0x0622, + CARD_NVIDIA_GEFORCE_9800GT = 0x0614, CARD_INTEL_845G = 0x2562, CARD_INTEL_I830G = 0x3577, CARD_INTEL_I855G = 0x3582, CARD_INTEL_I865G = 0x2572, CARD_INTEL_I915G = 0x2582, - CARD_INTEL_I915GM = 0x2592 + CARD_INTEL_I915GM = 0x2592, + CARD_INTEL_I945GM = 0x27a2, /* Same as GMA 950?? */ } GL_Cards; #define WINE_DEFAULT_VIDMEM 64*1024*1024 @@ -3145,6 +3294,7 @@ typedef enum _GL_PSVersion { /* OpenGL Supported Extensions (ARB and EXT) */ typedef enum _GL_SupportedExt { /* ARB */ + ARB_COLOR_BUFFER_FLOAT, ARB_DRAW_BUFFERS, ARB_FRAGMENT_PROGRAM, ARB_FRAGMENT_SHADER, @@ -3165,13 +3315,17 @@ typedef enum _GL_SupportedExt { ARB_TEXTURE_BORDER_CLAMP, ARB_TEXTURE_MIRRORED_REPEAT, ARB_TEXTURE_NON_POWER_OF_TWO, + ARB_TEXTURE_RECTANGLE, ARB_VERTEX_PROGRAM, ARB_VERTEX_BLEND, ARB_VERTEX_BUFFER_OBJECT, ARB_VERTEX_SHADER, ARB_SHADER_OBJECTS, /* EXT */ + EXT_BLEND_COLOR, EXT_BLEND_MINMAX, + EXT_BLEND_EQUATION_SEPARATE, + EXT_BLEND_FUNC_SEPARATE, EXT_FOG_COORD, EXT_FRAMEBUFFER_OBJECT, EXT_FRAMEBUFFER_BLIT, @@ -3183,6 +3337,7 @@ typedef enum _GL_SupportedExt { EXT_STENCIL_WRAP, EXT_TEXTURE3D, EXT_TEXTURE_COMPRESSION_S3TC, + EXT_TEXTURE_COMPRESSION_RGTC, EXT_TEXTURE_FILTER_ANISOTROPIC, EXT_TEXTURE_LOD, EXT_TEXTURE_LOD_BIAS, @@ -3190,7 +3345,7 @@ typedef enum _GL_SupportedExt { EXT_TEXTURE_ENV_COMBINE, EXT_TEXTURE_ENV_DOT3, EXT_TEXTURE_SRGB, - EXT_VERTEX_WEIGHTING, + EXT_GPU_PROGRAM_PARAMETERS, /* NVIDIA */ NV_HALF_FLOAT, NV_FOG_DISTANCE, @@ -3210,23 +3365,31 @@ typedef enum _GL_SupportedExt { NV_VERTEX_PROGRAM3, NV_FENCE, NV_DEPTH_CLAMP, + NV_LIGHT_MAX_EXPONENT, /* ATI */ ATI_SEPARATE_STENCIL, ATI_TEXTURE_ENV_COMBINE3, ATI_TEXTURE_MIRROR_ONCE, EXT_VERTEX_SHADER, ATI_ENVMAP_BUMPMAP, + ATI_FRAGMENT_SHADER, + ATI_TEXTURE_COMPRESSION_3DC, /* APPLE */ APPLE_FENCE, APPLE_CLIENT_STORAGE, APPLE_FLUSH_RENDER, APPLE_YCBCR_422, + APPLE_FLOAT_PIXELS, /* SGI */ SGI_VIDEO_SYNC, SGIS_GENERATE_MIPMAP, + /* Internally used */ + WINE_NORMALIZED_TEXRECT, + /* WGL extensions */ WGL_ARB_PBUFFER, + WGL_WINE_PIXEL_FORMAT_PASSTHROUGH, OPENGL_SUPPORTED_EXT_END } GL_SupportedExt; @@ -3237,275 +3400,300 @@ typedef enum _GL_SupportedExt { ****************************************************/ #define GL_EXT_FUNCS_GEN \ /** ARB Extensions **/ \ + /* GL_ARB_color_buffer_float */ \ + USE_GL_FUNC(PGLFNCLAMPCOLORARBPROC, glClampColorARB, ARB_COLOR_BUFFER_FLOAT, NULL )\ /* GL_ARB_draw_buffers */ \ - USE_GL_FUNC(PGLFNDRAWBUFFERSARBPROC, glDrawBuffersARB, ARB_DRAW_BUFFERS, NULL );\ + USE_GL_FUNC(PGLFNDRAWBUFFERSARBPROC, glDrawBuffersARB, ARB_DRAW_BUFFERS, NULL )\ /* GL_ARB_imaging, GL_EXT_blend_minmax */ \ - USE_GL_FUNC(PGLFNBLENDCOLORPROC, glBlendColorEXT, EXT_BLEND_MINMAX, NULL );\ - USE_GL_FUNC(PGLFNBLENDEQUATIONPROC, glBlendEquationEXT, EXT_BLEND_MINMAX, NULL );\ + USE_GL_FUNC(PGLFNBLENDCOLORPROC, glBlendColorEXT, EXT_BLEND_COLOR, NULL )\ + USE_GL_FUNC(PGLFNBLENDEQUATIONPROC, glBlendEquationEXT, EXT_BLEND_MINMAX, NULL )\ /* GL_ARB_multisample */ \ - USE_GL_FUNC(WINED3D_PFNGLSAMPLECOVERAGEARBPROC, glSampleCoverageARB, ARB_MULTISAMPLE, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLSAMPLECOVERAGEARBPROC, glSampleCoverageARB, ARB_MULTISAMPLE, NULL )\ /* GL_ARB_multitexture */ \ - USE_GL_FUNC(WINED3D_PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCLIENTACTIVETEXTUREARBPROC, glClientActiveTextureARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD1FARBPROC, glMultiTexCoord1fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD2FARBPROC, glMultiTexCoord2fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD3FARBPROC, glMultiTexCoord3fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD4FARBPROC, glMultiTexCoord4fARB, ARB_MULTITEXTURE, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCLIENTACTIVETEXTUREARBPROC, glClientActiveTextureARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD1FARBPROC, glMultiTexCoord1fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD2FARBPROC, glMultiTexCoord2fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD3FARBPROC, glMultiTexCoord3fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD4FARBPROC, glMultiTexCoord4fARB, ARB_MULTITEXTURE, NULL )\ /* GL_ARB_occlusion_query */ \ - USE_GL_FUNC(PGLFNGENQUERIESARBPROC, glGenQueriesARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNDELETEQUERIESARBPROC, glDeleteQueriesARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNBEGINQUERYARBPROC, glBeginQueryARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNENDQUERYARBPROC, glEndQueryARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB, ARB_OCCLUSION_QUERY, NULL );\ + USE_GL_FUNC(PGLFNGENQUERIESARBPROC, glGenQueriesARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNDELETEQUERIESARBPROC, glDeleteQueriesARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNBEGINQUERYARBPROC, glBeginQueryARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNENDQUERYARBPROC, glEndQueryARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB, ARB_OCCLUSION_QUERY, NULL )\ /* GL_ARB_point_parameters */ \ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFARBPROC, glPointParameterfARB, ARB_POINT_PARAMETERS, NULL );\ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVARBPROC, glPointParameterfvARB, ARB_POINT_PARAMETERS, NULL );\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFARBPROC, glPointParameterfARB, ARB_POINT_PARAMETERS, NULL )\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVARBPROC, glPointParameterfvARB, ARB_POINT_PARAMETERS, NULL )\ /* GL_ARB_texture_compression */ \ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNGETCOMPRESSEDTEXIMAGEPROC, glGetCompressedTexImageARB, ARB_TEXTURE_COMPRESSION,NULL );\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNGETCOMPRESSEDTEXIMAGEPROC, glGetCompressedTexImageARB, ARB_TEXTURE_COMPRESSION,NULL )\ /* GL_ARB_vertex_blend */ \ - USE_GL_FUNC(PGLFNGLWEIGHTPOINTERARB, glWeightPointerARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTBV, glWeightbvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTSV, glWeightsvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTIV, glWeightivARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTFV, glWeightfvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTDV, glWeightdvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUBV, glWeightubvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUSV, glWeightusvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUIV, glWeightuivARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLVERTEXBLENDARB, glVertexBlendARB, ARB_VERTEX_BLEND, NULL );\ + USE_GL_FUNC(PGLFNGLWEIGHTPOINTERARB, glWeightPointerARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTBV, glWeightbvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTSV, glWeightsvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTIV, glWeightivARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTFV, glWeightfvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTDV, glWeightdvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUBV, glWeightubvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUSV, glWeightusvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUIV, glWeightuivARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLVERTEXBLENDARB, glVertexBlendARB, ARB_VERTEX_BLEND, NULL )\ /* GL_ARB_vertex_buffer_object */ \ - USE_GL_FUNC(PGLFNBINDBUFFERARBPROC, glBindBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNDELETEBUFFERSARBPROC, glDeleteBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGENBUFFERSARBPROC, glGenBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNISBUFFERARBPROC, glIsBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNBUFFERDATAARBPROC, glBufferDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNBUFFERSUBDATAARBPROC, glBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERSUBDATAARBPROC, glGetBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNMAPBUFFERARBPROC, glMapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNUNMAPBUFFERARBPROC, glUnmapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERPARAMETERIVARBPROC, glGetBufferParameterivARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC, glGetBufferPointervARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ + USE_GL_FUNC(PGLFNBINDBUFFERARBPROC, glBindBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNDELETEBUFFERSARBPROC, glDeleteBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGENBUFFERSARBPROC, glGenBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNISBUFFERARBPROC, glIsBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNBUFFERDATAARBPROC, glBufferDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNBUFFERSUBDATAARBPROC, glBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERSUBDATAARBPROC, glGetBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNMAPBUFFERARBPROC, glMapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNUNMAPBUFFERARBPROC, glUnmapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERPARAMETERIVARBPROC, glGetBufferParameterivARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC, glGetBufferPointervARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ /** EXT Extensions **/ \ + /* GL_EXT_blend_equation_separate */ \ + USE_GL_FUNC(PGLFNBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT, EXT_BLEND_FUNC_SEPARATE, NULL)\ + /* GL_EXT_blend_func_separate */ \ + USE_GL_FUNC(PGLFNBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT, EXT_BLEND_EQUATION_SEPARATE, NULL)\ /* GL_EXT_fog_coord */ \ - USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT, EXT_FOG_COORD, NULL );\ + USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT, EXT_FOG_COORD, NULL )\ /* GL_EXT_framebuffer_object */ \ - USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLISFRAMEBUFFEREXTPROC, glIsFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE1DEXTPROC, glFramebufferTexture1DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE3DEXTPROC, glFramebufferTexture3DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENERATEMIPMAPEXTPROC, glGenerateMipmapEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGETRENDERBUFFERPARAMETERIVEXTPROC, glGetRenderbufferParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC, glGetFramebufferAttachmentParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ + USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLISFRAMEBUFFEREXTPROC, glIsFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE1DEXTPROC, glFramebufferTexture1DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE3DEXTPROC, glFramebufferTexture3DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENERATEMIPMAPEXTPROC, glGenerateMipmapEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGETRENDERBUFFERPARAMETERIVEXTPROC, glGetRenderbufferParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC, glGetFramebufferAttachmentParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ /* GL_EXT_framebuffer_blit */ \ - USE_GL_FUNC(PGLFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT, EXT_FRAMEBUFFER_BLIT, NULL );\ + USE_GL_FUNC(PGLFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT, EXT_FRAMEBUFFER_BLIT, NULL )\ /* GL_EXT_paletted_texture */ \ - USE_GL_FUNC(PGLFNGLCOLORTABLEEXTPROC, glColorTableEXT, EXT_PALETTED_TEXTURE, NULL );\ + USE_GL_FUNC(PGLFNGLCOLORTABLEEXTPROC, glColorTableEXT, EXT_PALETTED_TEXTURE, NULL )\ /* GL_EXT_point_parameters */ \ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC, glPointParameterfEXT, EXT_POINT_PARAMETERS, NULL );\ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC, glPointParameterfvEXT, EXT_POINT_PARAMETERS, NULL );\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC, glPointParameterfEXT, EXT_POINT_PARAMETERS, NULL )\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC, glPointParameterfvEXT, EXT_POINT_PARAMETERS, NULL )\ /* GL_EXT_secondary_color */ \ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC, glSecondaryColor3ubEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC, glSecondaryColor3fEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC, glSecondaryColor3fvEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT, EXT_SECONDARY_COLOR, NULL );\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC, glSecondaryColor3ubEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC, glSecondaryColor3fEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC, glSecondaryColor3fvEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT, EXT_SECONDARY_COLOR, NULL )\ /* GL_EXT_texture3D */ \ - USE_GL_FUNC(PGLFNGLTEXIMAGE3DEXTPROC, glTexImage3DEXT, EXT_TEXTURE3D, glTexImage3D);\ - USE_GL_FUNC(PGLFNGLTEXSUBIMAGE3DEXTPROC, glTexSubImage3DEXT, EXT_TEXTURE3D, glTexSubImage3D);\ + USE_GL_FUNC(PGLFNGLTEXIMAGE3DEXTPROC, glTexImage3DEXT, EXT_TEXTURE3D, glTexImage3D)\ + USE_GL_FUNC(PGLFNGLTEXSUBIMAGE3DEXTPROC, glTexSubImage3DEXT, EXT_TEXTURE3D, glTexSubImage3D)\ /* GL_ARB_vertex_program */ \ - USE_GL_FUNC(PGLFNGENPROGRAMSARBPROC, glGenProgramsARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNBINDPROGRAMARBPROC, glBindProgramARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNPROGRAMSTRINGARBPROC, glProgramStringARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNDELETEPROGRAMSARBPROC, glDeleteProgramsARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1DARBPROC, glVertexAttrib1dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1DVARBPROC, glVertexAttrib1dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1FARBPROC, glVertexAttrib1fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1FVARBPROC, glVertexAttrib1fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1SARBPROC, glVertexAttrib1sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1SVARBPROC, glVertexAttrib1svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2DARBPROC, glVertexAttrib2dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2DVARBPROC, glVertexAttrib2dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2FARBPROC, glVertexAttrib2fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2FVARBPROC, glVertexAttrib2fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2SARBPROC, glVertexAttrib2sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2SVARBPROC, glVertexAttrib2svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3DARBPROC, glVertexAttrib3dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3DVARBPROC, glVertexAttrib3dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3FARBPROC, glVertexAttrib3fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3FVARBPROC, glVertexAttrib3fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3SARBPROC, glVertexAttrib3sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3SVARBPROC, glVertexAttrib3svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NBVARBPROC, glVertexAttrib4NbvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NIVARBPROC, glVertexAttrib4NivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NSVARBPROC, glVertexAttrib4NsvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBARBPROC, glVertexAttrib4NubARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBVARBPROC, glVertexAttrib4NubvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUIVARBPROC, glVertexAttrib4NuivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUSVARBPROC, glVertexAttrib4NusvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4BVARBPROC, glVertexAttrib4bvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4DARBPROC, glVertexAttrib4dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4DVARBPROC, glVertexAttrib4dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4FARBPROC, glVertexAttrib4fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4FVARBPROC, glVertexAttrib4fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4IVARBPROC, glVertexAttrib4ivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4SARBPROC, glVertexAttrib4sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4SVARBPROC, glVertexAttrib4svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4UBVARBPROC, glVertexAttrib4ubvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4UIVARBPROC, glVertexAttrib4uivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4USVARBPROC, glVertexAttrib4usvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNGETPROGRAMIVARBPROC, glGetProgramivARB, ARB_VERTEX_PROGRAM, NULL );\ + USE_GL_FUNC(PGLFNGENPROGRAMSARBPROC, glGenProgramsARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNBINDPROGRAMARBPROC, glBindProgramARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMSTRINGARBPROC, glProgramStringARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNDELETEPROGRAMSARBPROC, glDeleteProgramsARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETER4FVARBPROC, glProgramLocalParameter4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1DARBPROC, glVertexAttrib1dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1DVARBPROC, glVertexAttrib1dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1FARBPROC, glVertexAttrib1fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1FVARBPROC, glVertexAttrib1fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1SARBPROC, glVertexAttrib1sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1SVARBPROC, glVertexAttrib1svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2DARBPROC, glVertexAttrib2dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2DVARBPROC, glVertexAttrib2dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2FARBPROC, glVertexAttrib2fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2FVARBPROC, glVertexAttrib2fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2SARBPROC, glVertexAttrib2sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2SVARBPROC, glVertexAttrib2svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3DARBPROC, glVertexAttrib3dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3DVARBPROC, glVertexAttrib3dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3FARBPROC, glVertexAttrib3fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3FVARBPROC, glVertexAttrib3fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3SARBPROC, glVertexAttrib3sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3SVARBPROC, glVertexAttrib3svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NBVARBPROC, glVertexAttrib4NbvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NIVARBPROC, glVertexAttrib4NivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NSVARBPROC, glVertexAttrib4NsvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBARBPROC, glVertexAttrib4NubARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBVARBPROC, glVertexAttrib4NubvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUIVARBPROC, glVertexAttrib4NuivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUSVARBPROC, glVertexAttrib4NusvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4BVARBPROC, glVertexAttrib4bvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4DARBPROC, glVertexAttrib4dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4DVARBPROC, glVertexAttrib4dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4FARBPROC, glVertexAttrib4fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4FVARBPROC, glVertexAttrib4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4IVARBPROC, glVertexAttrib4ivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4SARBPROC, glVertexAttrib4sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4SVARBPROC, glVertexAttrib4svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4UBVARBPROC, glVertexAttrib4ubvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4UIVARBPROC, glVertexAttrib4uivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4USVARBPROC, glVertexAttrib4usvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNGETPROGRAMIVARBPROC, glGetProgramivARB, ARB_VERTEX_PROGRAM, NULL )\ /* GL_ARB_shader_objects */ \ - USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERFVARBPROC, glGetObjectParameterfvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETACTIVEUNIFORMARBPROC, glGetActiveUniformARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IARBPROC, glUniform2iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IARBPROC, glUniform3iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IARBPROC, glUniform4iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IVARBPROC, glUniform4ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX2FVARBPROC, glUniformMatrix2fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX3FVARBPROC, glUniformMatrix3fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX4FVARBPROC, glUniformMatrix4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniform4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniform4ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETINFOLOGARBPROC, glGetInfoLogARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLSHADERSOURCEARBPROC, glShaderSourceARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCOMPILESHADERARBPROC, glCompileShaderARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLATTACHOBJECTARBPROC, glAttachObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLLINKPROGRAMARBPROC, glLinkProgramARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLDETACHOBJECTARBPROC, glDetachObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLDELETEOBJECTARBPROC, glDeleteObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLVALIDATEPROGRAMARBPROC, glValidateProgramARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETATTACHEDOBJECTSARBPROC, glGetAttachedObjectsARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETHANDLEARBPROC, glGetHandleARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETSHADERSOURCEARBPROC, glGetShaderSourceARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLBINDATTRIBLOCATIONARBPROC, glBindAttribLocationARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocationARB, ARB_SHADER_OBJECTS, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERFVARBPROC, glGetObjectParameterfvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETACTIVEUNIFORMARBPROC, glGetActiveUniformARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IARBPROC, glUniform2iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IARBPROC, glUniform3iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IARBPROC, glUniform4iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IVARBPROC, glUniform4ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX2FVARBPROC, glUniformMatrix2fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX3FVARBPROC, glUniformMatrix3fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX4FVARBPROC, glUniformMatrix4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniform4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniform4ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETINFOLOGARBPROC, glGetInfoLogARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLSHADERSOURCEARBPROC, glShaderSourceARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCOMPILESHADERARBPROC, glCompileShaderARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLATTACHOBJECTARBPROC, glAttachObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLLINKPROGRAMARBPROC, glLinkProgramARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLDETACHOBJECTARBPROC, glDetachObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLDELETEOBJECTARBPROC, glDeleteObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLVALIDATEPROGRAMARBPROC, glValidateProgramARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETATTACHEDOBJECTSARBPROC, glGetAttachedObjectsARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETHANDLEARBPROC, glGetHandleARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETSHADERSOURCEARBPROC, glGetShaderSourceARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLBINDATTRIBLOCATIONARBPROC, glBindAttribLocationARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocationARB, ARB_SHADER_OBJECTS, NULL )\ /* GL_EXT_stencil_two_side */ \ - USE_GL_FUNC(PGLFNACTIVESTENCILFACEEXTPROC, glActiveStencilFaceEXT, EXT_STENCIL_TWO_SIDE, NULL );\ + USE_GL_FUNC(PGLFNACTIVESTENCILFACEEXTPROC, glActiveStencilFaceEXT, EXT_STENCIL_TWO_SIDE, NULL )\ /* GL_ATI_separate_stencil */ \ - USE_GL_FUNC(PGLFNSTENCILOPSEPARATEATIPROC, glStencilOpSeparateATI, ATI_SEPARATE_STENCIL, NULL );\ - USE_GL_FUNC(PGLFNSTENCILFUNCSEPARATEATIPROC, glStencilFuncSeparateATI, ATI_SEPARATE_STENCIL, NULL );\ + USE_GL_FUNC(PGLFNSTENCILOPSEPARATEATIPROC, glStencilOpSeparateATI, ATI_SEPARATE_STENCIL, NULL )\ + USE_GL_FUNC(PGLFNSTENCILFUNCSEPARATEATIPROC, glStencilFuncSeparateATI, ATI_SEPARATE_STENCIL, NULL )\ /* GL_NV_half_float */ \ - USE_GL_FUNC(PGLFNVERTEX2HNVPROC, glVertex2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX2HVNVPROC, glVertex2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX3HNVPROC, glVertex3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX3HVNVPROC, glVertex3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX4HNVPROC, glVertex4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX4HVNVPROC, glVertex4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNNORMAL3HNVPROC, glNormal3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNNORMAL3HVNVPROC, glNormal3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR3HNVPROC, glColor3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR3HVNVPROC, glColor3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR4HNVPROC, glColor4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR4HVNVPROC, glColor4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD1HNVPROC, glTexCoord1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD1HVNVPROC, glTexCoord1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD2HNVPROC, glTexCoord2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD2HVNVPROC, glTexCoord2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD3HNVPROC, glTexCoord3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD3HVNVPROC, glTexCoord3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD4HNVPROC, glTexCoord4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD4HVNVPROC, glTexCoord4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD1HNVPROC, glMultiTexCoord1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD1HVNVPROC, glMultiTexCoord1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD2HNVPROC, glMultiTexCoord2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD2HVNVPROC, glMultiTexCoord2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD3HNVPROC, glMultiTexCoord3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD3HVNVPROC, glMultiTexCoord3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD4HNVPROC, glMultiTexCoord4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD4HVNVPROC, glMultiTexCoord4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNFOGCOORDHNVPROC, glFogCoordhNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNFOGCOORDHVNVPROC, glFogCoordhvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNSECONDARYCOLOR3HNVPROC, glSecondaryColor3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNSECONDARYCOLOR3HVNVPROC, glSecondaryColor3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXWEIGHTHNVPROC, glVertexWeighthNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXWEIGHTHVNVPROC, glVertexWeighthvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1HNVPROC, glVertexAttrib1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1HVNVPROC, glVertexAttrib1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2HNVPROC, glVertexAttrib2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2HVNVPROC, glVertexAttrib2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3HNVPROC, glVertexAttrib3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3HVNVPROC, glVertexAttrib3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4HNVPROC, glVertexAttrib4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4HVNVPROC, glVertexAttrib4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS1HVNVPROC, glVertexAttribs1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS2HVNVPROC, glVertexAttribs2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS3HVNVPROC, glVertexAttribs3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS4HVNVPROC, glVertexAttribs4hvNV, NV_HALF_FLOAT, NULL );\ + USE_GL_FUNC(PGLFNVERTEX2HNVPROC, glVertex2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX2HVNVPROC, glVertex2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX3HNVPROC, glVertex3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX3HVNVPROC, glVertex3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX4HNVPROC, glVertex4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX4HVNVPROC, glVertex4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNNORMAL3HNVPROC, glNormal3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNNORMAL3HVNVPROC, glNormal3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR3HNVPROC, glColor3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR3HVNVPROC, glColor3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR4HNVPROC, glColor4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR4HVNVPROC, glColor4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD1HNVPROC, glTexCoord1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD1HVNVPROC, glTexCoord1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD2HNVPROC, glTexCoord2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD2HVNVPROC, glTexCoord2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD3HNVPROC, glTexCoord3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD3HVNVPROC, glTexCoord3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD4HNVPROC, glTexCoord4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD4HVNVPROC, glTexCoord4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD1HNVPROC, glMultiTexCoord1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD1HVNVPROC, glMultiTexCoord1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD2HNVPROC, glMultiTexCoord2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD2HVNVPROC, glMultiTexCoord2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD3HNVPROC, glMultiTexCoord3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD3HVNVPROC, glMultiTexCoord3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD4HNVPROC, glMultiTexCoord4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD4HVNVPROC, glMultiTexCoord4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNFOGCOORDHNVPROC, glFogCoordhNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNFOGCOORDHVNVPROC, glFogCoordhvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNSECONDARYCOLOR3HNVPROC, glSecondaryColor3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNSECONDARYCOLOR3HVNVPROC, glSecondaryColor3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXWEIGHTHNVPROC, glVertexWeighthNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXWEIGHTHVNVPROC, glVertexWeighthvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1HNVPROC, glVertexAttrib1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1HVNVPROC, glVertexAttrib1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2HNVPROC, glVertexAttrib2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2HVNVPROC, glVertexAttrib2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3HNVPROC, glVertexAttrib3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3HVNVPROC, glVertexAttrib3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4HNVPROC, glVertexAttrib4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4HVNVPROC, glVertexAttrib4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS1HVNVPROC, glVertexAttribs1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS2HVNVPROC, glVertexAttribs2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS3HVNVPROC, glVertexAttribs3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS4HVNVPROC, glVertexAttribs4hvNV, NV_HALF_FLOAT, NULL )\ /* GL_NV_register_combiners */ \ - USE_GL_FUNC(PGLFNCOMBINERINPUTNVPROC, glCombinerInputNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINEROUTPUTNVPROC, glCombinerOutputNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERFNVPROC, glCombinerParameterfNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERFVNVPROC, glCombinerParameterfvNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERINVPROC, glCombinerParameteriNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERIVNVPROC, glCombinerParameterivNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNFINALCOMBINERINPUTNVPROC, glFinalCombinerInputNV, NV_REGISTER_COMBINERS, NULL );\ + USE_GL_FUNC(PGLFNCOMBINERINPUTNVPROC, glCombinerInputNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINEROUTPUTNVPROC, glCombinerOutputNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERFNVPROC, glCombinerParameterfNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERFVNVPROC, glCombinerParameterfvNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERINVPROC, glCombinerParameteriNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERIVNVPROC, glCombinerParameterivNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNFINALCOMBINERINPUTNVPROC, glFinalCombinerInputNV, NV_REGISTER_COMBINERS, NULL )\ /* GL_NV_fence */ \ - USE_GL_FUNC(PGLFNGENFENCESNVPROC, glGenFencesNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNDELETEFENCESNVPROC, glDeleteFencesNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNSETFENCENVPROC, glSetFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTFENCENVPROC, glTestFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHFENCENVPROC, glFinishFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNISFENCENVPROC, glIsFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNGETFENCEIVNVPROC, glGetFenceivNV, NV_FENCE, NULL );\ + USE_GL_FUNC(PGLFNGENFENCESNVPROC, glGenFencesNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNDELETEFENCESNVPROC, glDeleteFencesNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNSETFENCENVPROC, glSetFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTFENCENVPROC, glTestFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHFENCENVPROC, glFinishFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNISFENCENVPROC, glIsFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNGETFENCEIVNVPROC, glGetFenceivNV, NV_FENCE, NULL )\ /* GL_APPLE_fence */ \ - USE_GL_FUNC(PGLFNGENFENCESAPPLEPROC, glGenFencesAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNDELETEFENCESAPPLEPROC, glDeleteFencesAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNSETFENCEAPPLEPROC, glSetFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTFENCEAPPLEPROC, glTestFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHFENCEAPPLEPROC, glFinishFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNISFENCEAPPLEPROC, glIsFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTOBJECTAPPLEPROC, glTestObjectAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHOBJECTAPPLEPROC, glFinishObjectAPPLE, APPLE_FENCE, NULL );\ + USE_GL_FUNC(PGLFNGENFENCESAPPLEPROC, glGenFencesAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNDELETEFENCESAPPLEPROC, glDeleteFencesAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNSETFENCEAPPLEPROC, glSetFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTFENCEAPPLEPROC, glTestFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHFENCEAPPLEPROC, glFinishFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNISFENCEAPPLEPROC, glIsFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTOBJECTAPPLEPROC, glTestObjectAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHOBJECTAPPLEPROC, glFinishObjectAPPLE, APPLE_FENCE, NULL )\ /* GL_ATI_envmap_bumpmap */ \ - USE_GL_FUNC(PGLFNTEXBUMPPARAMETERIVATIPROC, glTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNTEXBUMPPARAMETERFVATIPROC, glTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERIVATIPROC, glGetTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERFVATIPROC, glGetTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL );\ + USE_GL_FUNC(PGLFNTEXBUMPPARAMETERIVATIPROC, glTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNTEXBUMPPARAMETERFVATIPROC, glTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERIVATIPROC, glGetTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERFVATIPROC, glGetTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL )\ /* GLX_SGI_video_sync */ \ - USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI, SGI_VIDEO_SYNC, NULL );\ - USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI, SGI_VIDEO_SYNC, NULL );\ + USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\ + USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\ /* GL_APPLE_flush_render */ \ - USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderApple, APPLE_FLUSH_RENDER, NULL );\ - USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderApple, APPLE_FLUSH_RENDER, NULL ); + USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderApple, APPLE_FLUSH_RENDER, NULL )\ + USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderApple, APPLE_FLUSH_RENDER, NULL )\ + /* GL_EXT_gpu_program_parameters */ \ + USE_GL_FUNC(PGLFNPROGRAMENVPARAMETERS4FVEXTPROC, glProgramEnvParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\ + USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETERS4FVEXTPROC, glProgramLocalParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\ + /* GL_ATI_fragment_shader */ \ + USE_GL_FUNC(PGLFNGENFRAGMENTSHADERSATI, glGenFragmentShadersATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNBINDFRAGMENTSHADERATI, glBindFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNDELETEFRAGMENTSHADERATI, glDeleteFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNBEGINFRAGMENTSHADERATI, glBeginFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNENDFRAGMENTSHADERATI, glEndFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNPASSTEXCOORDATI, glPassTexCoordATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNSAMPLEMAPATI, glSampleMapATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP1ATI, glColorFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP2ATI, glColorFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP3ATI, glColorFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP1ATI, glAlphaFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP2ATI, glAlphaFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP3ATI, glAlphaFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNSETFRAGMENTSHADERCONSTANTATI, glSetFragmentShaderConstantATI, ATI_FRAGMENT_SHADER, NULL ) /**************************************************** * OpenGL WGL defines and functions pointer @@ -3513,6 +3701,11 @@ typedef enum _GL_SupportedExt { /* WGL_ARB_extensions_string */ typedef const char * (WINAPI * WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +/* WGL_ARB_multisample */ +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif /* WGL_ARB_pixel_format */ #ifndef WGL_ARB_pixel_format #define WGL_ARB_pixel_format 1 @@ -3594,19 +3787,22 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, #define WGL_ARB_pixel_format_float 1 #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 #endif +/* WGL_WINE_pixel_format_passthrough */ +typedef BOOL (WINAPI * WINED3D_PFNWGLSETPIXELFORMATWINE) (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR* ppfd); #define WGL_EXT_FUNCS_GEN \ - USE_GL_FUNC(WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB, 0, NULL); \ - 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_PFNWGLMAKECONTEXTCURRENTARBPROC, wglMakeContextCurrentARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLGETCURRENTREADDCARBPROC, wglGetCurrentReadDCARB, 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_PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB, 0, NULL) \ + 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_PFNWGLMAKECONTEXTCURRENTARBPROC, wglMakeContextCurrentARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLGETCURRENTREADDCARBPROC, wglGetCurrentReadDCARB, 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) /**************************************************** @@ -3614,10 +3810,20 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, ****************************************************/ typedef struct { - GLint glInternal, glGammaInternal, glFormat, glType; + GLint glInternal, glGammaInternal, rtInternal, glFormat, glType; WINED3DFORMAT conversion_group; + unsigned int Flags; + float heightscale; } GlPixelFormatDesc; +typedef struct _WINED3DGLTYPE { + int d3dType; + GLint size; + GLenum glType; + GLboolean normalized; + int typesize; +} WINED3DGLTYPE; + #define USE_GL_FUNC(type, pfn, ext, replace) type pfn; typedef struct _WineD3D_GL_Info { @@ -3627,7 +3833,8 @@ typedef struct _WineD3D_GL_Info { GL_Vendors gl_vendor; GL_Cards gl_card; UINT vidmem; - DWORD gl_driver_version; + DWORD driver_version; + DWORD driver_version_hipart; CHAR gl_renderer[255]; /** * CAPS Constants @@ -3646,8 +3853,8 @@ typedef struct _WineD3D_GL_Info { float max_pointsize, max_pointsizemin; UINT max_blends; UINT max_anisotropy; - UINT max_aux_buffers; UINT max_glsl_varyings; + float max_shininess; unsigned max_vshader_constantsF; unsigned max_pshader_constantsF; @@ -3669,15 +3876,19 @@ typedef struct _WineD3D_GL_Info { GL_VSVersion vs_ati_version; BOOL arb_vs_offset_limit; + BOOL set_texcoord_w; BOOL supported[OPENGL_SUPPORTED_EXT_END + 1]; /** OpenGL EXT and ARB functions ptr */ - GL_EXT_FUNCS_GEN; + GL_EXT_FUNCS_GEN /** OpenGL WGL functions ptr */ - WGL_EXT_FUNCS_GEN; + WGL_EXT_FUNCS_GEN GlPixelFormatDesc *gl_formats; + + /* Vertex data types */ + WINED3DGLTYPE glTypeLookup[WINED3DDECLTYPE_UNUSED]; } WineD3D_GL_Info; #undef USE_GL_FUNC diff --git a/reactos/include/reactos/wine/wined3d_interface.h b/reactos/include/reactos/wine/wined3d_interface.h index 6335eb98bbd..6ecab39e933 100644 --- a/reactos/include/reactos/wine/wined3d_interface.h +++ b/reactos/include/reactos/wine/wined3d_interface.h @@ -80,6 +80,7 @@ struct IWineD3DSurface; #define WINEDDERR_SURFACEBUSY MAKE_WINED3DHRESULT(430) #define WINEDDERR_INVALIDRECT MAKE_WINED3DHRESULT(150) #define WINEDDERR_NOCLIPLIST MAKE_WINED3DHRESULT(205) +#define WINEDDERR_OVERLAYNOTVISIBLE MAKE_WINED3DHRESULT(577) #define WINED3DOK_NOAUTOGEN MAKE_WINED3DSTATUS(2159) /***************************************************************************** @@ -247,6 +248,10 @@ typedef HRESULT (WINAPI *D3DCB_CREATEADDITIONALSWAPCHAIN) (IUnknown *pDevice, struct IWineD3DSwapChain **pSwapChain ); +typedef HRESULT (WINAPI *D3DCB_ENUMRESOURCES) (struct IWineD3DResource *resource, + void *pData + ); + /***************************************************************************** * Callback functions for custom implicit object destruction. */ @@ -305,7 +310,7 @@ DECLARE_INTERFACE_(IWineD3D, IWineD3DBase) STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQuality) PURE; STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, WINED3DFORMAT RenderTargetFormat, WINED3DFORMAT DepthStencilFormat) PURE; STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter, WINED3DDEVTYPE CheckType, WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) PURE; - STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) PURE; + STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) PURE; STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) PURE; STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS *pCaps) PURE; STDMETHOD(CreateDevice)(THIS_ UINT Adapter, WINED3DDEVTYPE DeviceType,HWND hFocusWindow, DWORD BehaviorFlags, struct IWineD3DDevice **ppReturnedDeviceInterface, IUnknown *parent) PURE; @@ -331,7 +336,7 @@ DECLARE_INTERFACE_(IWineD3D, IWineD3DBase) #define IWineD3D_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f) #define IWineD3D_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e) #define IWineD3D_CheckDeviceType(p,a,b,c,d,e) (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e) -#define IWineD3D_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f) +#define IWineD3D_CheckDeviceFormat(p,a,b,c,d,e,f,g) (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f,g) #define IWineD3D_CheckDeviceFormatConversion(p,a,b,c,d) (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d) #define IWineD3D_GetDeviceCaps(p,a,b,c) (p)->lpVtbl->GetDeviceCaps(p,a,b,c) #define IWineD3D_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f) @@ -362,15 +367,16 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) STDMETHOD(CreateVolume)(THIS_ UINT Width, UINT Height, UINT Depth, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, struct IWineD3DVolume** ppVolumeTexture, HANDLE* pSharedHandle, IUnknown *parent) PURE; STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, struct IWineD3DCubeTexture** ppCubeTexture, HANDLE* pSharedHandle, IUnknown *parent, D3DCB_CREATESURFACEFN pFn) PURE; STDMETHOD(CreateQuery)(THIS_ WINED3DQUERYTYPE Type, struct IWineD3DQuery **ppQuery, IUnknown *pParent); - STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS *pPresentationParameters, struct IWineD3DSwapChain **pSwapChain, IUnknown *pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2); - STDMETHOD(CreateVertexDeclaration)(THIS_ struct IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent, const WINED3DVERTEXELEMENT *elements, size_t element_count) PURE; + STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS *pPresentationParameters, struct IWineD3DSwapChain **pSwapChain, IUnknown *pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2, WINED3DSURFTYPE surface_type); + STDMETHOD(CreateVertexDeclaration)(THIS_ struct IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent, const WINED3DVERTEXELEMENT *elements, UINT element_count) PURE; STDMETHOD(CreateVertexDeclarationFromFVF)(THIS_ struct IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent, DWORD Fvf) PURE; STDMETHOD(CreateVertexShader)(THIS_ struct IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD* pFunction, struct IWineD3DVertexShader** ppShader, IUnknown *pParent) PURE; STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, struct IWineD3DPixelShader** ppShader, IUnknown *pParent) PURE; STDMETHOD_(HRESULT,CreatePalette)(THIS_ DWORD Flags, PALETTEENTRY *PalEnt, struct IWineD3DPalette **Palette, IUnknown *Parent); STDMETHOD(Init3D)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain); + STDMETHOD(InitGDI)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain); STDMETHOD(Uninit3D)(THIS, D3DCB_DESTROYSURFACEFN pFn, D3DCB_DESTROYSWAPCHAINFN pFn2); - STDMETHOD_(void, SetFullscreen)(THIS_ BOOL fullscreen); + STDMETHOD(UninitGDI)(THIS, D3DCB_DESTROYSWAPCHAINFN pFn2); STDMETHOD_(void, SetMultithreaded)(THIS); STDMETHOD(EvictManagedResources)(THIS) PURE; STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE; @@ -380,8 +386,6 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) STDMETHOD(GetDirect3D)(THIS_ IWineD3D** ppD3D) PURE; STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, WINED3DDISPLAYMODE* pMode) PURE; STDMETHOD(SetDisplayMode)(THIS_ UINT iSwapChain, WINED3DDISPLAYMODE* pMode) PURE; - STDMETHOD(GetHWND)(THIS_ HWND *hwnd) PURE; - STDMETHOD(SetHWND)(THIS_ HWND hwnd) PURE; STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE; STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) PURE; STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, struct IWineD3DSwapChain **pSwapChain) PURE; @@ -482,6 +486,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,struct IWineD3DSurface* pSurface) PURE; /*** object tracking ***/ STDMETHOD_(void, ResourceReleased)(THIS_ struct IWineD3DResource *resource); + STDMETHOD(EnumResources)(THIS_ D3DCB_ENUMRESOURCES pCallback, void *pData); }; #undef INTERFACE @@ -502,15 +507,16 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) #define IWineD3DDevice_CreateVolume(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateVolume(p,a,b,c,d,e,f,g,h,i) #define IWineD3DDevice_CreateCubeTexture(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g,h,i) #define IWineD3DDevice_CreateQuery(p,a,b,c) (p)->lpVtbl->CreateQuery(p,a,b,c) -#define IWineD3DDevice_CreateAdditionalSwapChain(p,a,b,c,d,e) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b,c,d,e) +#define IWineD3DDevice_CreateAdditionalSwapChain(p,a,b,c,d,e,f) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b,c,d,e,f) #define IWineD3DDevice_CreateVertexDeclaration(p,a,b,c,d) (p)->lpVtbl->CreateVertexDeclaration(p,a,b,c,d) #define IWineD3DDevice_CreateVertexDeclarationFromFVF(p,a,b,c) (p)->lpVtbl->CreateVertexDeclarationFromFVF(p,a,b,c) #define IWineD3DDevice_CreateVertexShader(p,a,b,c,d) (p)->lpVtbl->CreateVertexShader(p,a,b,c,d) #define IWineD3DDevice_CreatePixelShader(p,a,b,c) (p)->lpVtbl->CreatePixelShader(p,a,b,c) #define IWineD3DDevice_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) #define IWineD3DDevice_Init3D(p, a, b) (p)->lpVtbl->Init3D(p, a, b) +#define IWineD3DDevice_InitGDI(p, a, b) (p)->lpVtbl->InitGDI(p, a, b) #define IWineD3DDevice_Uninit3D(p, a, b) (p)->lpVtbl->Uninit3D(p, a, b) -#define IWineD3DDevice_SetFullscreen(p, a) (p)->lpVtbl->SetFullscreen(p, a) +#define IWineD3DDevice_UninitGDI(p, a) (p)->lpVtbl->UninitGDI(p, a) #define IWineD3DDevice_SetMultithreaded(p) (p)->lpVtbl->SetMultithreaded(p) #define IWineD3DDevice_EvictManagedResources(p) (p)->lpVtbl->EvictManagedResources(p) #define IWineD3DDevice_GetAvailableTextureMem(p) (p)->lpVtbl->GetAvailableTextureMem(p) @@ -520,8 +526,6 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) #define IWineD3DDevice_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a) #define IWineD3DDevice_GetDisplayMode(p,a,b) (p)->lpVtbl->GetDisplayMode(p,a,b) #define IWineD3DDevice_SetDisplayMode(p,a,b) (p)->lpVtbl->SetDisplayMode(p,a,b) -#define IWineD3DDevice_GetHWND(p, a) (p)->lpVtbl->GetHWND(p, a) -#define IWineD3DDevice_SetHWND(p, a) (p)->lpVtbl->SetHWND(p, a) #define IWineD3DDevice_GetNumberOfSwapChains(p) (p)->lpVtbl->GetNumberOfSwapChains(p) #define IWineD3DDevice_Reset(p,a) (p)->lpVtbl->Reset(p,a) #define IWineD3DDevice_SetDialogBoxMode(p,a) (p)->lpVtbl->SetDialogBoxMode(p,a) @@ -621,6 +625,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase) #define IWineD3DDevice_UpdateSurface(p,a,b,c,d) (p)->lpVtbl->UpdateSurface(p,a,b,c,d) #define IWineD3DDevice_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b) #define IWineD3DDevice_ResourceReleased(p,a) (p)->lpVtbl->ResourceReleased(p,a) +#define IWineD3DDevice_EnumResources(p,a,b) (p)->lpVtbl->EnumResources(p,a,b) #endif /***************************************************************************** @@ -643,6 +648,7 @@ DECLARE_INTERFACE_(IWineD3DResource,IWineD3DBase) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; }; #undef INTERFACE @@ -662,6 +668,7 @@ DECLARE_INTERFACE_(IWineD3DResource,IWineD3DBase) #define IWineD3DResource_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DResource_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DResource_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DResource_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DResource_GetType(p) (p)->lpVtbl->GetType(p) #endif @@ -685,6 +692,7 @@ DECLARE_INTERFACE_(IWineD3DVertexBuffer,IWineD3DResource) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DVertexBuffer methods ***/ STDMETHOD(Lock)(THIS_ UINT OffsetToLock, UINT SizeToLock, BYTE ** ppbData, DWORD Flags) PURE; @@ -708,6 +716,7 @@ DECLARE_INTERFACE_(IWineD3DVertexBuffer,IWineD3DResource) #define IWineD3DVertexBuffer_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DVertexBuffer_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DVertexBuffer_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DVertexBuffer_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DVertexBuffer_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DVertexBuffer methods ***/ #define IWineD3DVertexBuffer_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) @@ -735,6 +744,7 @@ DECLARE_INTERFACE_(IWineD3DIndexBuffer,IWineD3DResource) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DIndexBuffer methods ***/ STDMETHOD(Lock)(THIS_ UINT OffsetToLock, UINT SizeToLock, BYTE ** ppbData, DWORD Flags) PURE; @@ -758,6 +768,7 @@ DECLARE_INTERFACE_(IWineD3DIndexBuffer,IWineD3DResource) #define IWineD3DIndexBuffer_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DIndexBuffer_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DIndexBuffer_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DIndexBuffer_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DIndexBuffer_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DIndexBuffer methods ***/ #define IWineD3DIndexBuffer_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) @@ -787,6 +798,7 @@ DECLARE_INTERFACE_(IWineD3DBaseTexture,IWineD3DResource) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DBaseTexture methods ***/ STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; @@ -798,8 +810,8 @@ DECLARE_INTERFACE_(IWineD3DBaseTexture,IWineD3DResource) STDMETHOD_(BOOL, SetDirty)(THIS_ BOOL) PURE; STDMETHOD_(BOOL, GetDirty)(THIS) PURE; STDMETHOD(BindTexture)(THIS) PURE; - STDMETHOD(UnBindTexture)(THIS) PURE; STDMETHOD_(UINT, GetTextureDimensions)(THIS) PURE; + STDMETHOD_(BOOL, IsCondNP2)(THIS) PURE; STDMETHOD_(void, ApplyStateChanges)(THIS_ const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) PURE; }; @@ -820,6 +832,7 @@ DECLARE_INTERFACE_(IWineD3DBaseTexture,IWineD3DResource) #define IWineD3DBaseTexture_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DBaseTexture_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DBaseTexture_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DBaseTexture_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DBaseTexture_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DBaseTexture methods ***/ #define IWineD3DBaseTexture_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) @@ -832,8 +845,8 @@ DECLARE_INTERFACE_(IWineD3DBaseTexture,IWineD3DResource) #define IWineD3DBaseTexture_GetDirty(p) (p)->lpVtbl->GetDirty(p) /*** internal methods ***/ #define IWineD3DBaseTexture_BindTexture(p) (p)->lpVtbl->BindTexture(p) -#define IWineD3DBaseTexture_UnBindTexture(p) (p)->lpVtbl->UnBindTexture(p) #define IWineD3DBaseTexture_GetTextureDimensions(p) (p)->lpVtbl->GetTextureDimensions(p) +#define IWineD3DBaseTexture_IsCondNP2(p) (p)->lpVtbl->IsCondNP2(p) #define IWineD3DBaseTexture_ApplyStateChanges(p,a,b) (p)->lpVtbl->ApplyStateChanges(p,a,b) #endif @@ -857,6 +870,7 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DBaseTexture methods ***/ STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; @@ -868,8 +882,8 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) STDMETHOD_(BOOL, SetDirty)(THIS_ BOOL) PURE; STDMETHOD_(BOOL, GetDirty)(THIS) PURE; STDMETHOD(BindTexture)(THIS) PURE; - STDMETHOD(UnBindTexture)(THIS) PURE; STDMETHOD_(UINT, GetTextureDimensions)(THIS) PURE; + STDMETHOD_(BOOL, IsCondNP2)(THIS) PURE; STDMETHOD_(void, ApplyStateChanges)(THIS_ const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) PURE; /*** IWineD3DTexture methods ***/ STDMETHOD_(void, Destroy)(THIS_ D3DCB_DESTROYSURFACEFN pFn) PURE; @@ -896,6 +910,7 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) #define IWineD3DTexture_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DTexture_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DTexture_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DTexture_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DTexture_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DTexture methods: IWineD3DBaseTexture ***/ #define IWineD3DTexture_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) @@ -907,8 +922,8 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) #define IWineD3DTexture_SetDirty(p,a) (p)->lpVtbl->SetDirty(p,a) #define IWineD3DTexture_GetDirty(p) (p)->lpVtbl->GetDirty(p) #define IWineD3DTexture_BindTexture(p) (p)->lpVtbl->BindTexture(p) -#define IWineD3DTexture_UnBindTexture(p) (p)->lpVtbl->UnBindTexture(p) #define IWineD3DTexture_GetTextureDimensions(p) (p)->lpVtbl->GetTextureDimensions(p) +#define IWineD3DTexture_IsCondNP2(p) (p)->lpVtbl->IsCondNP2(p) #define IWineD3DTexture_ApplyStateChanges(p,a,b) (p)->lpVtbl->ApplyStateChanges(p,a,b) /*** IWineD3DTexture methods ***/ #define IWineD3DTexture_Destroy(p,a) (p)->lpVtbl->Destroy(p,a) @@ -939,6 +954,7 @@ DECLARE_INTERFACE_(IWineD3DCubeTexture,IWineD3DBaseTexture) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DBaseTexture methods ***/ STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; @@ -950,8 +966,8 @@ DECLARE_INTERFACE_(IWineD3DCubeTexture,IWineD3DBaseTexture) STDMETHOD_(BOOL, SetDirty)(THIS_ BOOL) PURE; STDMETHOD_(BOOL, GetDirty)(THIS) PURE; STDMETHOD(BindTexture)(THIS) PURE; - STDMETHOD(UnBindTexture)(THIS) PURE; STDMETHOD_(UINT, GetTextureDimensions)(THIS) PURE; + STDMETHOD_(BOOL, IsCondNP2)(THIS) PURE; STDMETHOD_(void, ApplyStateChanges)(THIS_ DWORD const textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) PURE; /*** IWineD3DCubeTexture methods ***/ STDMETHOD_(void, Destroy)(THIS_ D3DCB_DESTROYSURFACEFN pFn) PURE; @@ -978,6 +994,7 @@ DECLARE_INTERFACE_(IWineD3DCubeTexture,IWineD3DBaseTexture) #define IWineD3DCubeTexture_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DCubeTexture_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DCubeTexture_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DCubeTexture_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DCubeTexture_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DCubeTexture methods: IWineD3DBaseTexture ***/ #define IWineD3DCubeTexture_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) @@ -989,8 +1006,8 @@ DECLARE_INTERFACE_(IWineD3DCubeTexture,IWineD3DBaseTexture) #define IWineD3DCubeTexture_SetDirty(p,a) (p)->lpVtbl->SetDirty(p,a) #define IWineD3DCubeTexture_GetDirty(p) (p)->lpVtbl->GetDirty(p) #define IWineD3DCubeTexture_BindTexture(p) (p)->lpVtbl->BindTexture(p) -#define IWineD3DCubeTexture_UnBindTexture(p) (p)->lpVtbl->UnBindTexture(p) #define IWineD3DCubeTexture_GetTextureDimensions(p) (p)->lpVtbl->GetTextureDimensions(p) +#define IWineD3DCubeTexture_IsCondNP2(p) (p)->lpVtbl->IsCondNP2(p) #define IWineD3DCubeTexture_ApplyStateChanges(p,a,b) (p)->lpVtbl->ApplyStateChanges(p,a,b) /*** IWineD3DCubeTexture methods ***/ #define IWineD3DCubeTexture_Destroy(p,a) (p)->lpVtbl->Destroy(p,a) @@ -1022,6 +1039,7 @@ DECLARE_INTERFACE_(IWineD3DVolumeTexture,IWineD3DBaseTexture) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DBaseTexture methods ***/ STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; @@ -1033,8 +1051,8 @@ DECLARE_INTERFACE_(IWineD3DVolumeTexture,IWineD3DBaseTexture) STDMETHOD_(BOOL, SetDirty)(THIS_ BOOL) PURE; STDMETHOD_(BOOL, GetDirty)(THIS) PURE; STDMETHOD(BindTexture)(THIS) PURE; - STDMETHOD(UnBindTexture)(THIS) PURE; STDMETHOD_(UINT, GetTextureDimensions)(THIS) PURE; + STDMETHOD_(BOOL, IsCondNP2)(THIS) PURE; STDMETHOD_(void, ApplyStateChanges)(THIS_ const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) PURE; /*** IWineD3DVolumeTexture methods ***/ STDMETHOD_(void, Destroy)(THIS_ D3DCB_DESTROYVOLUMEFN pFn) PURE; @@ -1061,6 +1079,7 @@ DECLARE_INTERFACE_(IWineD3DVolumeTexture,IWineD3DBaseTexture) #define IWineD3DVolumeTexture_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DVolumeTexture_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DVolumeTexture_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DVolumeTexture_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DVolumeTexture_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DVolumeTexture methods: IWineD3DBaseTexture ***/ #define IWineD3DVolumeTexture_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) @@ -1072,8 +1091,8 @@ DECLARE_INTERFACE_(IWineD3DVolumeTexture,IWineD3DBaseTexture) #define IWineD3DVolumeTexture_SetDirty(p,a) (p)->lpVtbl->SetDirty(p,a) #define IWineD3DVolumeTexture_GetDirty(p) (p)->lpVtbl->GetDirty(p) #define IWineD3DVolumeTexture_BindTexture(p) (p)->lpVtbl->BindTexture(p) -#define IWineD3DVolumeTexture_UnBindTexture(p) (p)->lpVtbl->UnBindTexture(p) #define IWineD3DVolumeTexture_GetTextureDimensions(p) (p)->lpVtbl->GetTextureDimensions(p) +#define IWineD3DVolumeTexture_IsCondNP2(p) (p)->lpVtbl->IsCondNP2(p) #define IWineD3DVolumeTexture_ApplyStateChanges(p,a,b) (p)->lpVtbl->ApplyStateChanges(p,a,b) /*** IWineD3DVolumeTexture methods ***/ #define IWineD3DVolumeTexture_Destroy(p,a) (p)->lpVtbl->Destroy(p,a) @@ -1104,6 +1123,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; STDMETHOD_(WINED3DRESOURCETYPE,GetType)(THIS) PURE; /*** IWineD3DSurface methods ***/ STDMETHOD(GetContainer)(THIS_ REFIID riid, void ** ppContainer) PURE; @@ -1144,6 +1164,8 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) STDMETHOD(PrivateSetup)(THIS) PURE; STDMETHOD_(void,ModifyLocation)(THIS_ DWORD flag, BOOL persistent); STDMETHOD(LoadLocation)(THIS_ DWORD flag, const RECT *rect); + STDMETHOD_(WINED3DSURFTYPE,GetImplType)(THIS); + STDMETHOD(DrawOverlay)(THIS); }; #undef INTERFACE @@ -1162,6 +1184,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) #define IWineD3DSurface_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DSurface_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DSurface_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DSurface_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DSurface_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DSurface methods ***/ #define IWineD3DSurface_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b) @@ -1201,7 +1224,9 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) #define IWineD3DSurface_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) #define IWineD3DSurface_PrivateSetup(p) (p)->lpVtbl->PrivateSetup(p) #define IWineD3DSurface_ModifyLocation(p,a,b) (p)->lpVtbl->ModifyLocation(p,a,b) -#define IWineD3DSurface_LoadLocation(p,a,b) (p)->lpVtbl->LoadLocation(p,a,b) +#define IWineD3DSurface_LoadLocation(p,a,b) (p)->lpVtbl->LoadLocation(p,a,b) +#define IWineD3DSurface_GetImplType(p) (p)->lpVtbl->GetImplType(p) +#define IWineD3DSurface_DrawOverlay(p) (p)->lpVtbl->DrawOverlay(p) #endif /***************************************************************************** @@ -1224,7 +1249,8 @@ DECLARE_INTERFACE_(IWineD3DVolume,IWineD3DResource) STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD PriorityNew) PURE; STDMETHOD_(DWORD,GetPriority)(THIS) PURE; STDMETHOD_(void,PreLoad)(THIS) PURE; - STDMETHOD_(WINED3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD_(void,UnLoad)(THIS) PURE; + STDMETHOD_(WINED3DRESOURCETYPE, GetType)(THIS) PURE; /*** IWineD3DVolume methods ***/ STDMETHOD(GetContainer)(THIS_ REFIID riid, void ** ppContainer) PURE; STDMETHOD(GetDesc)(THIS_ WINED3DVOLUME_DESC * pDesc) PURE; @@ -1252,6 +1278,7 @@ DECLARE_INTERFACE_(IWineD3DVolume,IWineD3DResource) #define IWineD3DVolume_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) #define IWineD3DVolume_GetPriority(p) (p)->lpVtbl->GetPriority(p) #define IWineD3DVolume_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IWineD3DVolume_UnLoad(p) (p)->lpVtbl->UnLoad(p) #define IWineD3DVolume_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DVolume methods ***/ #define IWineD3DVolume_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b) @@ -1278,8 +1305,8 @@ DECLARE_INTERFACE_(IWineD3DVertexDeclaration,IWineD3DBase) STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE; /*** IWineD3DVertexDeclaration methods ***/ STDMETHOD(GetDevice)(THIS_ IWineD3DDevice **ppDevice) PURE; - STDMETHOD(GetDeclaration)(THIS_ WINED3DVERTEXELEMENT *elements, size_t *elements_count) PURE; - STDMETHOD(SetDeclaration)(THIS_ const WINED3DVERTEXELEMENT *elements, size_t element_count) PURE; + STDMETHOD(GetDeclaration)(THIS_ WINED3DVERTEXELEMENT *elements, UINT *elements_count) PURE; + STDMETHOD(SetDeclaration)(THIS_ const WINED3DVERTEXELEMENT *elements, UINT element_count) PURE; }; #undef INTERFACE @@ -1386,6 +1413,7 @@ DECLARE_INTERFACE_(IWineD3DSwapChain,IWineD3DBase) STDMETHOD_(void, Destroy)(THIS_ D3DCB_DESTROYSURFACEFN pFn) PURE; STDMETHOD(GetDevice)(THIS_ IWineD3DDevice **ppDevice) PURE; STDMETHOD(Present)(THIS_ CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) PURE; + STDMETHOD(SetDestWindowOverride)(THIS_ HWND window); STDMETHOD(GetFrontBufferData)(THIS_ IWineD3DSurface *pDestSurface) PURE; STDMETHOD(GetBackBuffer)(THIS_ UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) PURE; STDMETHOD(GetRasterStatus)(THIS_ WINED3DRASTER_STATUS *pRasterStatus) PURE; @@ -1407,6 +1435,7 @@ DECLARE_INTERFACE_(IWineD3DSwapChain,IWineD3DBase) #define IWineD3DSwapChain_Destroy(p,a) (p)->lpVtbl->Destroy(p,a) #define IWineD3DSwapChain_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) #define IWineD3DSwapChain_Present(p,a,b,c,d,e) (p)->lpVtbl->Present(p,a,b,c,d,e) +#define IWineD3DSwapChain_SetDestWindowOverride(p,a) (p)->lpVtbl->SetDestWindowOverride(p,a) #define IWineD3DSwapChain_GetFrontBufferData(p,a) (p)->lpVtbl->GetFrontBufferData(p,a) #define IWineD3DSwapChain_GetBackBuffer(p,a,b,c) (p)->lpVtbl->GetBackBuffer(p,a,b,c) #define IWineD3DSwapChain_GetRasterStatus(p,a) (p)->lpVtbl->GetRasterStatus(p,a) diff --git a/reactos/include/reactos/wine/wined3d_types.h b/reactos/include/reactos/wine/wined3d_types.h index 477df2479c1..5b722e775c0 100644 --- a/reactos/include/reactos/wine/wined3d_types.h +++ b/reactos/include/reactos/wine/wined3d_types.h @@ -266,6 +266,7 @@ typedef enum _WINED3DFORMAT { WINED3DFMT_UYVY = WINEMAKEFOURCC('U', 'Y', 'V', 'Y'), WINED3DFMT_YUY2 = WINEMAKEFOURCC('Y', 'U', 'Y', '2'), + WINED3DFMT_YV12 = WINEMAKEFOURCC('Y', 'V', '1', '2'), WINED3DFMT_DXT1 = WINEMAKEFOURCC('D', 'X', 'T', '1'), WINED3DFMT_DXT2 = WINEMAKEFOURCC('D', 'X', 'T', '2'), WINED3DFMT_DXT3 = WINEMAKEFOURCC('D', 'X', 'T', '3'), @@ -302,6 +303,10 @@ typedef enum _WINED3DFORMAT { WINED3DFMT_CxV8U8 = 117, + /* Vendor specific formats */ + WINED3DFMT_ATI2N = WINEMAKEFOURCC('A', 'T', 'I', '2'), + WINED3DFMT_NVHU = WINEMAKEFOURCC('N', 'V', 'H', 'U'), + WINED3DFMT_NVHS = WINEMAKEFOURCC('N', 'V', 'H', 'S'), WINED3DFMT_FORCE_DWORD = 0xFFFFFFFF } WINED3DFORMAT; @@ -1095,112 +1100,134 @@ typedef struct _WINED3DINDEXBUFFER_DESC { */ typedef struct _WINED3DVSHADERCAPS2_0 { - DWORD *Caps; - INT *DynamicFlowControlDepth; - INT *NumTemps; - INT *StaticFlowControlDepth; + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; } WINED3DVSHADERCAPS2_0; typedef struct _WINED3DPSHADERCAPS2_0 { - DWORD *Caps; - INT *DynamicFlowControlDepth; - INT *NumTemps; - INT *StaticFlowControlDepth; - INT *NumInstructionSlots; + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; } WINED3DPSHADERCAPS2_0; +typedef struct _WINEDDCAPS { + DWORD Caps; + DWORD Caps2; + DWORD CKeyCaps; + DWORD FXCaps; + DWORD FXAlphaCaps; + DWORD PalCaps; + DWORD SVCaps; + DWORD SVBCaps; + DWORD SVBCKeyCaps; + DWORD SVBFXCaps; + DWORD VSBCaps; + DWORD VSBCKeyCaps; + DWORD VSBFXCaps; + DWORD SSBCaps; + DWORD SSBCKeyCaps; + DWORD SSBFXCaps; + DWORD ddsCaps; + DWORD StrideAlign; +} WINEDDCAPS; + typedef struct _WINED3DCAPS { - WINED3DDEVTYPE *DeviceType; - UINT *AdapterOrdinal; + WINED3DDEVTYPE DeviceType; + UINT AdapterOrdinal; - DWORD *Caps; - DWORD *Caps2; - DWORD *Caps3; - DWORD *PresentationIntervals; + DWORD Caps; + DWORD Caps2; + DWORD Caps3; + DWORD PresentationIntervals; - DWORD *CursorCaps; + DWORD CursorCaps; - DWORD *DevCaps; + DWORD DevCaps; - DWORD *PrimitiveMiscCaps; - DWORD *RasterCaps; - DWORD *ZCmpCaps; - DWORD *SrcBlendCaps; - DWORD *DestBlendCaps; - DWORD *AlphaCmpCaps; - DWORD *ShadeCaps; - DWORD *TextureCaps; - DWORD *TextureFilterCaps; - DWORD *CubeTextureFilterCaps; - DWORD *VolumeTextureFilterCaps; - DWORD *TextureAddressCaps; - DWORD *VolumeTextureAddressCaps; + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD ZCmpCaps; + DWORD SrcBlendCaps; + DWORD DestBlendCaps; + DWORD AlphaCmpCaps; + DWORD ShadeCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; + DWORD CubeTextureFilterCaps; + DWORD VolumeTextureFilterCaps; + DWORD TextureAddressCaps; + DWORD VolumeTextureAddressCaps; - DWORD *LineCaps; + DWORD LineCaps; - DWORD *MaxTextureWidth; - DWORD *MaxTextureHeight; - DWORD *MaxVolumeExtent; + DWORD MaxTextureWidth; + DWORD MaxTextureHeight; + DWORD MaxVolumeExtent; - DWORD *MaxTextureRepeat; - DWORD *MaxTextureAspectRatio; - DWORD *MaxAnisotropy; - float *MaxVertexW; + DWORD MaxTextureRepeat; + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + float MaxVertexW; - float *GuardBandLeft; - float *GuardBandTop; - float *GuardBandRight; - float *GuardBandBottom; + float GuardBandLeft; + float GuardBandTop; + float GuardBandRight; + float GuardBandBottom; - float *ExtentsAdjust; - DWORD *StencilCaps; + float ExtentsAdjust; + DWORD StencilCaps; - DWORD *FVFCaps; - DWORD *TextureOpCaps; - DWORD *MaxTextureBlendStages; - DWORD *MaxSimultaneousTextures; + DWORD FVFCaps; + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; - DWORD *VertexProcessingCaps; - DWORD *MaxActiveLights; - DWORD *MaxUserClipPlanes; - DWORD *MaxVertexBlendMatrices; - DWORD *MaxVertexBlendMatrixIndex; + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; - float *MaxPointSize; + float MaxPointSize; - DWORD *MaxPrimitiveCount; - DWORD *MaxVertexIndex; - DWORD *MaxStreams; - DWORD *MaxStreamStride; + DWORD MaxPrimitiveCount; + DWORD MaxVertexIndex; + DWORD MaxStreams; + DWORD MaxStreamStride; - DWORD *VertexShaderVersion; - DWORD *MaxVertexShaderConst; + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; - DWORD *PixelShaderVersion; - float *PixelShader1xMaxValue; + DWORD PixelShaderVersion; + float PixelShader1xMaxValue; /* DX 9 */ - DWORD *DevCaps2; + DWORD DevCaps2; - float *MaxNpatchTessellationLevel; - DWORD *Reserved5; /*undocumented*/ + float MaxNpatchTessellationLevel; + DWORD Reserved5; /*undocumented*/ - UINT *MasterAdapterOrdinal; - UINT *AdapterOrdinalInGroup; - UINT *NumberOfAdaptersInGroup; - DWORD *DeclTypes; - DWORD *NumSimultaneousRTs; - DWORD *StretchRectFilterCaps; + UINT MasterAdapterOrdinal; + UINT AdapterOrdinalInGroup; + UINT NumberOfAdaptersInGroup; + DWORD DeclTypes; + DWORD NumSimultaneousRTs; + DWORD StretchRectFilterCaps; WINED3DVSHADERCAPS2_0 VS20Caps; WINED3DPSHADERCAPS2_0 PS20Caps; - DWORD *VertexTextureFilterCaps; - DWORD *MaxVShaderInstructionsExecuted; - DWORD *MaxPShaderInstructionsExecuted; - DWORD *MaxVertexShader30InstructionSlots; - DWORD *MaxPixelShader30InstructionSlots; - DWORD *Reserved2;/* Not in the microsoft headers but documented */ - DWORD *Reserved3; + DWORD VertexTextureFilterCaps; + DWORD MaxVShaderInstructionsExecuted; + DWORD MaxPShaderInstructionsExecuted; + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; + DWORD Reserved2;/* Not in the microsoft headers but documented */ + DWORD Reserved3; + WINEDDCAPS DirectDrawCaps; } WINED3DCAPS; typedef enum _WINED3DSTATEBLOCKTYPE { @@ -1259,11 +1286,11 @@ typedef enum _WINED3DDECLTYPE { #define WINED3DDECL_END() {0xFF,0,WINED3DDECLTYPE_UNUSED,0,0,0,-1} typedef struct WineDirect3DStridedData { - BYTE *lpData; /* Pointer to start of data */ - DWORD dwStride; /* Stride between occurances of this data */ - DWORD dwType; /* Type (as in D3DVSDT_TYPE) */ - int VBO; /* Vertex buffer object this data is in */ - UINT streamNo; /* D3D stream number */ + BYTE *lpData; /* Pointer to start of data */ + DWORD dwStride; /* Stride between occurrences of this data */ + DWORD dwType; /* Type (as in D3DVSDT_TYPE) */ + int VBO; /* Vertex buffer object this data is in */ + UINT streamNo; /* D3D stream number */ } WineDirect3DStridedData; typedef struct WineDirect3DVertexStridedData { @@ -1333,7 +1360,7 @@ typedef enum { #define WINED3DUSAGE_AUTOGENMIPMAP 0x00000400L #define WINED3DUSAGE_DMAP 0x00004000L #define WINED3DUSAGE_MASK 0x00004FFFL -#define WINED3DUSAGE_OVERLAY 0x00010000L +#define WINED3DUSAGE_OVERLAY 0x80000000L #define WINED3DUSAGE_QUERY_LEGACYBUMPMAP 0x00008000L #define WINED3DUSAGE_QUERY_FILTER 0x00020000L @@ -1342,13 +1369,12 @@ typedef enum { #define WINED3DUSAGE_QUERY_SRGBWRITE 0x00040000L #define WINED3DUSAGE_QUERY_VERTEXTEXTURE 0x00100000L #define WINED3DUSAGE_QUERY_WRAPANDMIP 0x00200000L -#define WINED3DUSAGE_QUERY_MASK 0x002F8000L +#define WINED3DUSAGE_QUERY_MASK 0x003F8000L typedef enum _WINED3DSURFTYPE { SURFACE_UNKNOWN = 0, /* Default / Unknown surface type */ SURFACE_OPENGL, /* OpenGL surface: Renders using libGL, needed for 3D */ SURFACE_GDI, /* User surface. No 3D, DirectDraw rendering with GDI */ - SURFACE_XRENDER /* Future dreams: Use XRENDER / EXA / whatever stuff */ } WINED3DSURFTYPE; #define WINED3DCAPS2_NO2DDURING3DSCENE 0x00000002L @@ -1778,4 +1804,28 @@ typedef struct _WINEDDOVERLAYFX #define WINEDDFLIP_INTERVAL3 0x03000000 #define WINEDDFLIP_INTERVAL4 0x04000000 +#define WINEDDOVER_ALPHADEST 0x00000001 +#define WINEDDOVER_ALPHADESTCONSTOVERRIDE 0x00000002 +#define WINEDDOVER_ALPHADESTNEG 0x00000004 +#define WINEDDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008 +#define WINEDDOVER_ALPHAEDGEBLEND 0x00000010 +#define WINEDDOVER_ALPHASRC 0x00000020 +#define WINEDDOVER_ALPHASRCCONSTOVERRIDE 0x00000040 +#define WINEDDOVER_ALPHASRCNEG 0x00000080 +#define WINEDDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100 +#define WINEDDOVER_HIDE 0x00000200 +#define WINEDDOVER_KEYDEST 0x00000400 +#define WINEDDOVER_KEYDESTOVERRIDE 0x00000800 +#define WINEDDOVER_KEYSRC 0x00001000 +#define WINEDDOVER_KEYSRCOVERRIDE 0x00002000 +#define WINEDDOVER_SHOW 0x00004000 +#define WINEDDOVER_ADDDIRTYRECT 0x00008000 +#define WINEDDOVER_REFRESHDIRTYRECTS 0x00010000 +#define WINEDDOVER_REFRESHALL 0x00020000 +#define WINEDDOVER_DDFX 0x00080000 +#define WINEDDOVER_AUTOFLIP 0x00100000 +#define WINEDDOVER_BOB 0x00200000 +#define WINEDDOVER_OVERRIDEBOBWEAVE 0x00400000 +#define WINEDDOVER_INTERLEAVED 0x00800000 + #endif