diff --git a/reactos/dll/directx/wine/d3d8/cubetexture.c b/reactos/dll/directx/wine/d3d8/cubetexture.c index 32511d6569c..d0b8f724ec0 100644 --- a/reactos/dll/directx/wine/d3d8/cubetexture.c +++ b/reactos/dll/directx/wine/d3d8/cubetexture.c @@ -57,9 +57,11 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 ifa if (ref == 0) { TRACE("Releasing child %p\n", This->wineD3DCubeTexture); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D8CB_DestroySurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -73,14 +75,15 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_GetDevice(LPDIRECT3DCUBETEXTURE8 HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetDevice(This->wineD3DCubeTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -89,9 +92,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_SetPrivateData(LPDIRECT3DCUBETEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_SetPrivateData(This->wineD3DCubeTexture,refguid,pData,SizeOfData,Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -100,9 +104,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_GetPrivateData(LPDIRECT3DCUBETEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetPrivateData(This->wineD3DCubeTexture,refguid,pData,pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -111,9 +116,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_FreePrivateData(LPDIRECT3DCUBETE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_FreePrivateData(This->wineD3DCubeTexture,refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -122,9 +128,10 @@ static DWORD WINAPI IDirect3DCubeTexture8Impl_SetPriority(LPDIRECT3DCUBETEXTURE8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_SetPriority(This->wineD3DCubeTexture, PriorityNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -133,9 +140,10 @@ static DWORD WINAPI IDirect3DCubeTexture8Impl_GetPriority(LPDIRECT3DCUBETEXTURE8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_GetPriority(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -143,9 +151,9 @@ static void WINAPI IDirect3DCubeTexture8Impl_PreLoad(LPDIRECT3DCUBETEXTURE8 ifac IDirect3DCubeTexture8Impl *This = (IDirect3DCubeTexture8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DCubeTexture_PreLoad(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DCubeTexture8Impl_GetType(LPDIRECT3DCUBETEXTURE8 iface) { @@ -153,9 +161,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DCubeTexture8Impl_GetType(LPDIRECT3DCUBETE D3DRESOURCETYPE type; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); type = IWineD3DCubeTexture_GetType(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return type; } @@ -165,9 +174,10 @@ static DWORD WINAPI IDirect3DCubeTexture8Impl_SetLOD(LPDIRECT3DCUBETEXTURE8 ifac DWORD lod; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); lod = IWineD3DCubeTexture_SetLOD(This->wineD3DCubeTexture, LODNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return lod; } @@ -176,9 +186,10 @@ static DWORD WINAPI IDirect3DCubeTexture8Impl_GetLOD(LPDIRECT3DCUBETEXTURE8 ifac DWORD lod; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); lod = IWineD3DCubeTexture_GetLOD((LPDIRECT3DBASETEXTURE8) This); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return lod; } @@ -187,9 +198,10 @@ static DWORD WINAPI IDirect3DCubeTexture8Impl_GetLevelCount(LPDIRECT3DCUBETEXTUR DWORD cnt; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); cnt = IWineD3DCubeTexture_GetLevelCount(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return cnt; } @@ -201,22 +213,21 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_GetLevelDesc(LPDIRECT3DCUBETEXTU TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = NULL; /* DirectX9 only */ - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetLevelDesc(This->wineD3DCubeTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -228,13 +239,14 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_GetCubeMapSurface(LPDIRECT3DCUBE TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DCubeTexture_GetCubeMapSurface(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level, &mySurface); if (hrc == D3D_OK && NULL != ppCubeMapSurface) { IWineD3DCubeTexture_GetParent(mySurface, (IUnknown **)ppCubeMapSurface); IWineD3DCubeTexture_Release(mySurface); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -243,9 +255,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_LockRect(LPDIRECT3DCUBETEXTURE8 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_LockRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -254,9 +267,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_UnlockRect(LPDIRECT3DCUBETEXTURE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_UnlockRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -265,9 +279,10 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_AddDirtyRect(LPDIRECT3DCUBETEXTU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_AddDirtyRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, pDirtyRect); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d8/d3d8_main.c b/reactos/dll/directx/wine/d3d8/d3d8_main.c index 8e32dc3f9ad..6300371842a 100644 --- a/reactos/dll/directx/wine/d3d8/d3d8_main.c +++ b/reactos/dll/directx/wine/d3d8/d3d8_main.c @@ -24,15 +24,6 @@ #include "d3d8_private.h" #include "wine/debug.h" -static CRITICAL_SECTION_DEBUG d3d8_cs_debug = -{ - 0, 0, &d3d8_cs, - { &d3d8_cs_debug.ProcessLocksList, - &d3d8_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": d3d8_cs") } -}; -CRITICAL_SECTION d3d8_cs = { &d3d8_cs_debug, -1, 0, 0, 0, 0 }; - WINE_DEFAULT_DEBUG_CHANNEL(d3d8); HRESULT WINAPI D3D8GetSWInfo(void) { @@ -48,7 +39,8 @@ IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion) { IDirect3D8Impl* object; TRACE("SDKVersion = %x\n", SDKVersion); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3D8Impl)); object->lpVtbl = &Direct3D8_Vtbl; @@ -56,7 +48,8 @@ IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion) { object->WineD3D = WineDirect3DCreate(8, (IUnknown *)object); TRACE("Created Direct3D object @ %p, WineObj @ %p\n", object, object->WineD3D); - LeaveCriticalSection(&d3d8_cs); + + wined3d_mutex_unlock(); if (!object->WineD3D) { @@ -77,14 +70,14 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) } /*********************************************************************** - * ValidateVertexShader (D3D8.@) + * ValidateVertexShader (D3D8.@) * * I've seen reserved1 and reserved2 always passed as 0's - * bool seems always passed as 0 or 1, but other values work as well.... + * bool seems always passed as 0 or 1, but other values work as well... * toto result? */ HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto) -{ +{ HRESULT ret; FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, bool, toto); @@ -96,7 +89,7 @@ HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD switch(*vertexshader) { case 0xFFFE0101: - case 0xFFFE0100: + case 0xFFFE0100: ret=S_OK; break; default: @@ -108,7 +101,7 @@ HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD } /*********************************************************************** - * ValidatePixelShader (D3D8.@) + * ValidatePixelShader (D3D8.@) * * PARAMS * toto result? @@ -117,12 +110,12 @@ HRESULT WINAPI ValidatePixelShader(DWORD* pixelshader, DWORD* reserved1, BOOL bo { HRESULT ret; FIXME("(%p %p %d %p): stub\n", pixelshader, reserved1, bool, toto); - + if (!pixelshader) return E_FAIL; if (reserved1) - return E_FAIL; + return E_FAIL; switch(*pixelshader) { case 0xFFFF0100: diff --git a/reactos/dll/directx/wine/d3d8/d3d8_private.h b/reactos/dll/directx/wine/d3d8/d3d8_private.h index c38d8cc8b30..52abb84b5ec 100644 --- a/reactos/dll/directx/wine/d3d8/d3d8_private.h +++ b/reactos/dll/directx/wine/d3d8/d3d8_private.h @@ -97,6 +97,8 @@ _pD3D8Caps->PixelShaderVersion = _pWineCaps->PixelShaderVersion; \ _pD3D8Caps->MaxPixelShaderValue = _pWineCaps->PixelShader1xMaxValue; +void fixup_caps(WINED3DCAPS *pWineCaps); + /* Direct3D8 Interfaces: */ typedef struct IDirect3DBaseTexture8Impl IDirect3DBaseTexture8Impl; typedef struct IDirect3DVolumeTexture8Impl IDirect3DVolumeTexture8Impl; @@ -120,9 +122,6 @@ typedef struct IDirect3DVertexShaderDeclarationImpl IDirect3DVertexShaderDeclara /* Advance declaration of structures to satisfy compiler */ typedef struct IDirect3DVertexShader8Impl IDirect3DVertexShader8Impl; -/* Global critical section */ -extern CRITICAL_SECTION d3d8_cs; - /* =========================================================================== The interfaces themselves =========================================================================== */ @@ -166,10 +165,24 @@ extern const IWineD3DDeviceParentVtbl d3d8_wined3d_device_parent_vtbl; #define D3D8_INITIAL_HANDLE_TABLE_SIZE 64 #define D3D8_INVALID_HANDLE ~0U +enum d3d8_handle_type +{ + D3D8_HANDLE_FREE, + D3D8_HANDLE_VS, + D3D8_HANDLE_PS, + D3D8_HANDLE_SB, +}; + +struct d3d8_handle_entry +{ + void *object; + enum d3d8_handle_type type; +}; + struct d3d8_handle_table { - void **entries; - void **free_entries; + struct d3d8_handle_entry *entries; + struct d3d8_handle_entry *free_entries; UINT table_size; UINT entry_count; }; @@ -455,7 +468,7 @@ struct IDirect3DVolumeTexture8Impl /* TODO: Generate a valid GUIDs */ /* {83B073CE-6F30-11d9-C687-00046142C14F} */ -DEFINE_GUID(IID_IDirect3DStateBlock8, +DEFINE_GUID(IID_IDirect3DStateBlock8, 0x83b073ce, 0x6f30, 0x11d9, 0xc6, 0x87, 0x0, 0x4, 0x61, 0x42, 0xc1, 0x4f); DEFINE_GUID(IID_IDirect3DVertexDeclaration8, diff --git a/reactos/dll/directx/wine/d3d8/device.c b/reactos/dll/directx/wine/d3d8/device.c index 206697d99d4..675eac134f3 100644 --- a/reactos/dll/directx/wine/d3d8/device.c +++ b/reactos/dll/directx/wine/d3d8/device.c @@ -69,6 +69,7 @@ D3DFORMAT d3dformat_from_wined3dformat(WINED3DFORMAT format) case WINED3DFMT_X8L8V8U8: return D3DFMT_X8L8V8U8; case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8; case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16; + case WINED3DFMT_W11V11U10: return D3DFMT_W11V11U10; case WINED3DFMT_A2W10V10U10: return D3DFMT_A2W10V10U10; case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE; case WINED3DFMT_D32: return D3DFMT_D32; @@ -119,6 +120,7 @@ WINED3DFORMAT wined3dformat_from_d3dformat(D3DFORMAT format) case D3DFMT_X8L8V8U8: return WINED3DFMT_X8L8V8U8; case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM; case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM; + case D3DFMT_W11V11U10: return WINED3DFMT_W11V11U10; case D3DFMT_A2W10V10U10: return WINED3DFMT_A2W10V10U10; case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE; case D3DFMT_D32: return WINED3DFMT_D32; @@ -163,14 +165,23 @@ static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, U } /* Handle table functions */ -static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object) +static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type) { + struct d3d8_handle_entry *entry; + if (t->free_entries) { /* Use a free handle */ - void **entry = t->free_entries; - t->free_entries = *entry; - *entry = object; + entry = t->free_entries; + if (entry->type != D3D8_HANDLE_FREE) + { + ERR("Handle %u(%p) is in the free list, but has type %#x.\n", (entry - t->entries), entry, entry->type); + return D3D8_INVALID_HANDLE; + } + t->free_entries = entry->object; + entry->object = object; + entry->type = type; + return entry - t->entries; } @@ -178,34 +189,68 @@ static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object) { /* Grow the table */ UINT new_size = t->table_size + (t->table_size >> 1); - void **new_entries = HeapReAlloc(GetProcessHeap(), 0, t->entries, new_size * sizeof(void *)); - if (!new_entries) return D3D8_INVALID_HANDLE; + struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(), + 0, t->entries, new_size * sizeof(*t->entries)); + if (!new_entries) + { + ERR("Failed to grow the handle table.\n"); + return D3D8_INVALID_HANDLE; + } t->entries = new_entries; t->table_size = new_size; } - t->entries[t->entry_count] = object; + entry = &t->entries[t->entry_count]; + entry->object = object; + entry->type = type; + return t->entry_count++; } -static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle) +static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) { - void **entry, *object; + struct d3d8_handle_entry *entry; + void *object; - if (handle >= t->entry_count) return NULL; + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } entry = &t->entries[handle]; - object = *entry; - *entry = t->free_entries; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + object = entry->object; + entry->object = t->free_entries; + entry->type = D3D8_HANDLE_FREE; t->free_entries = entry; return object; } -static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle) +static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) { - if (handle >= t->entry_count) return NULL; - return t->entries[handle]; + struct d3d8_handle_entry *entry; + + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } + + entry = &t->entries[handle]; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + return entry->object; } /* IDirect3D IUnknown parts follow: */ @@ -254,7 +299,9 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) { unsigned i; TRACE("Releasing wined3d device %p\n", This->WineD3DDevice); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); + This->inDestruction = TRUE; for(i = 0; i < This->numConvertedDecls; i++) { @@ -266,7 +313,8 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) { IWineD3DDevice_Release(This->WineD3DDevice); HeapFree(GetProcessHeap(), 0, This->handle_table.entries); HeapFree(GetProcessHeap(), 0, This); - LeaveCriticalSection(&d3d8_cs); + + wined3d_mutex_unlock(); } return ref; } @@ -277,9 +325,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -288,9 +338,11 @@ static UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_GetAvailableTextureMem(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -299,9 +351,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3 HRESULT hr; TRACE("(%p) : Relay bytes(%d)\n", This, Bytes); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_EvictManagedResources(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -316,7 +370,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDirect3D(This->WineD3DDevice, &pWineD3D); if (hr == D3D_OK && pWineD3D != NULL) { @@ -326,8 +380,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, FIXME("Call to IWineD3DDevice_GetDirect3D failed\n"); *ppD3D8 = NULL; } + wined3d_mutex_unlock(); + TRACE("(%p) returning %p\n",This , *ppD3D8); - LeaveCriticalSection(&d3d8_cs); return hr; } @@ -346,21 +401,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */ } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pWineCaps); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + + fixup_caps(pWineCaps); WINECAPSTOD3D8CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); - /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ - if(pCaps->PixelShaderVersion > D3DPS_VERSION(1,4)){ - pCaps->PixelShaderVersion = D3DPS_VERSION(1,4); - } - if(pCaps->VertexShaderVersion > D3DVS_VERSION(1,1)){ - pCaps->VertexShaderVersion = D3DVS_VERSION(1,1); - } - pCaps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst); - TRACE("Returning %p %p\n", This, pCaps); return hrc; } @@ -370,9 +418,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDisplayMode(This->WineD3DDevice, 0, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -384,9 +432,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVIC HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetCreationParameters(This->WineD3DDevice, (WINED3DDEVICE_CREATION_PARAMETERS *) pParameters); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -400,9 +449,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 return WINED3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice,XHotSpot,YHotSpot,pSurface->wineD3DSurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -410,9 +460,9 @@ static void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 ifac IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetCursorPosition(This->WineD3DDevice, XScreenSpace, YScreenSpace, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) { @@ -420,9 +470,10 @@ static BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL BOOL ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DDevice_ShowCursor(This->WineD3DDevice, bShow); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -465,10 +516,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DD localParameters.PresentationInterval = pPresentationParameters->FullScreen_PresentationInterval; localParameters.AutoRestoreDisplayMode = TRUE; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown *)object, SURFACE_OPENGL); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; @@ -520,9 +571,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRE localParameters.PresentationInterval = pPresentationParameters->FullScreen_PresentationInterval; localParameters.AutoRestoreDisplayMode = TRUE; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_Reset(This->WineD3DDevice, &localParameters); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; @@ -546,9 +597,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONS HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_Present(This->WineD3DDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -559,13 +611,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); 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); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return rc; } @@ -574,9 +627,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 ifa HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetRasterStatus(This->WineD3DDevice, 0, (WINED3DRASTER_STATUS *) pRasterStatus); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -585,9 +639,9 @@ static void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DW TRACE("(%p) Relay\n", This); /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetGammaRamp(This->WineD3DDevice, 0, Flags, (CONST WINED3DGAMMARAMP *) pRamp); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) { @@ -595,9 +649,9 @@ static void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3 TRACE("(%p) Relay\n", This); /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_GetGammaRamp(This->WineD3DDevice, 0, (WINED3DGAMMARAMP *) pRamp); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, @@ -619,13 +673,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface object->lpVtbl = &Direct3DTexture8_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (FAILED(hrc)) { - /* free up object */ + /* free up object */ FIXME("(%p) call to IWineD3DDevice_CreateTexture failed\n", This); HeapFree(GetProcessHeap(), 0, object); /* *ppTexture = NULL; */ @@ -639,10 +694,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface return hrc; } -static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, - UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, - D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) { - +static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(IDirect3DDevice8 *iface, + UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, + D3DPOOL Pool, IDirect3DVolumeTexture8 **ppVolumeTexture) +{ IDirect3DVolumeTexture8Impl *object; IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; HRESULT hrc = D3D_OK; @@ -659,11 +714,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels, Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DVolumeTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (hrc != D3D_OK) { @@ -680,9 +736,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 return hrc; } -static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage, - D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) { - +static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(IDirect3DDevice8 *iface, UINT EdgeLength, + UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8 **ppCubeTexture) +{ IDirect3DCubeTexture8Impl *object; IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; HRESULT hr = D3D_OK; @@ -700,10 +756,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 i object->lpVtbl = &Direct3DCubeTexture8_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (hr != D3D_OK){ @@ -737,10 +794,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage & WINED3DUSAGE_MASK, 0 /* fvf for ddraw only */, (WINED3DPOOL)Pool, &object->wineD3DVertexBuffer, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + object->fvf = FVF; if (D3D_OK != hrc) { @@ -775,10 +834,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 i object->ref = 1; object->format = wined3dformat_from_d3dformat(Format); TRACE("Calling wined3d create index buffer\n"); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage & WINED3DUSAGE_MASK, (WINED3DPOOL)Pool, &object->wineD3DIndexBuffer, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (D3D_OK != hrc) { @@ -794,7 +854,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 i return hrc; } -static HRESULT IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface8 **ppSurface,D3DRESOURCETYPE Type, UINT Usage,D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality) { +static HRESULT IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, + D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface8 **ppSurface, + UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality) +{ HRESULT hrc; IDirect3DSurface8Impl *object; IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; @@ -823,11 +886,12 @@ static HRESULT IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface, UINT TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p\n", This, Width, Height, Format, *ppSurface); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, wined3dformat_from_d3dformat(Format), - Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage & WINED3DUSAGE_MASK, - (WINED3DPOOL)Pool, MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object); - LeaveCriticalSection(&d3d8_cs); + Lockable, Discard, Level, &object->wineD3DSurface, Usage & WINED3DUSAGE_MASK, (WINED3DPOOL)Pool, + MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object); + wined3d_mutex_unlock(); + if (hrc != D3D_OK || NULL == object->wineD3DSurface) { /* free up object */ FIXME("(%p) call to IWineD3DDevice_CreateSurface failed\n", This); @@ -845,7 +909,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 HRESULT hr; TRACE("Relay\n"); - hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, Lockable, FALSE /* Discard */, 0 /* Level */ , ppSurface, D3DRTYPE_SURFACE, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, MultiSample, 0); + hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, Lockable, FALSE /* Discard */, + 0 /* Level */, ppSurface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, MultiSample, 0); + return hr; } @@ -854,9 +920,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DD TRACE("Relay\n"); /* TODO: Verify that Discard is false */ - hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, FALSE, 0 /* Level */ - ,ppSurface, D3DRTYPE_SURFACE, D3DUSAGE_DEPTHSTENCIL, - D3DPOOL_DEFAULT, MultiSample, 0); + hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, FALSE, + 0 /* Level */, ppSurface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, MultiSample, 0); + return hr; } @@ -865,8 +931,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 HRESULT hr; TRACE("Relay\n"); - 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 */); + hr = IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, FALSE /* Discard */, + 0 /* Level */, ppSurface, 0 /* Usage (undefined/none) */, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, + 0 /* MultisampleQuality */); + return hr; } @@ -886,25 +954,23 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, ID /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */ - memset(&winedesc, 0, sizeof(winedesc)); - winedesc.Format = &srcFormat; - winedesc.Width = &srcWidth; - winedesc.Height = &srcHeight; - winedesc.Size = &srcSize; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DSurface_GetDesc(Source->wineD3DSurface, &winedesc); + srcFormat = winedesc.format; + srcWidth = winedesc.width; + srcHeight = winedesc.height; + srcSize = winedesc.size; - winedesc.Format = &destFormat; - winedesc.Width = &destWidth; - winedesc.Height = &destHeight; - winedesc.Size = NULL; IWineD3DSurface_GetDesc(Dest->wineD3DSurface, &winedesc); + destFormat = winedesc.format; + destWidth = winedesc.width; + destHeight = winedesc.height; /* Check that the source and destination formats match */ if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) { WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", iface, pSourceSurface, pDestinationSurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return WINED3DERR_INVALIDCALL; } else if (WINED3DFMT_UNKNOWN == destFormat) { TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", iface); @@ -928,7 +994,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, ID } } } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -938,9 +1004,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_UpdateTexture(This->WineD3DDevice, ((IDirect3DBaseTexture8Impl *)pSourceTexture)->wineD3DBaseTexture, ((IDirect3DBaseTexture8Impl *)pDestinationTexture)->wineD3DBaseTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -956,9 +1023,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 ifac return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetFrontBufferData(This->WineD3DDevice, 0, destSurface->wineD3DSurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -970,7 +1038,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 ifa HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice, &original_ds); if (hr == WINED3D_OK || hr == WINED3DERR_NOTFOUND) @@ -982,7 +1050,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 ifa } if (original_ds) IWineD3DSurface_Release(original_ds); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -996,7 +1065,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 i if (ppRenderTarget == NULL) { return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_GetRenderTarget(This->WineD3DDevice, 0, &pRenderTarget); if (hr == D3D_OK && pRenderTarget != NULL) { @@ -1006,7 +1076,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 i FIXME("Call to IWineD3DDevice_GetRenderTarget failed\n"); *ppRenderTarget = NULL; } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -1021,7 +1091,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDE return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr=IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice,&pZStencilSurface); if (hr == WINED3D_OK) { IWineD3DSurface_GetParent(pZStencilSurface,(IUnknown**)ppZStencilSurface); @@ -1031,7 +1101,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDE FIXME("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr); *ppZStencilSurface = NULL; } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -1041,9 +1111,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) { HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_BeginScene(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1052,9 +1123,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) { HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_EndScene(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1064,9 +1136,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD TRACE("(%p) Relay\n" , This); /* Note: D3DRECT is compatible with WINED3DRECT */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_Clear(This->WineD3DDevice, Count, (CONST WINED3DRECT*) pRects, Flags, Color, Z, Stencil); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1076,9 +1149,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTransform(This->WineD3DDevice, State, (CONST WINED3DMATRIX*) lpMatrix); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1088,9 +1162,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetTransform(This->WineD3DDevice, State, (WINED3DMATRIX*) pMatrix); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1100,9 +1175,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 i TRACE("(%p) Relay\n" , This); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_MultiplyTransform(This->WineD3DDevice, State, (CONST WINED3DMATRIX*) pMatrix); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1112,9 +1188,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DVIEWPORT8 is compatible with WINED3DVIEWPORT */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetViewport(This->WineD3DDevice, (const WINED3DVIEWPORT *)pViewport); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1124,9 +1201,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DVIEWPORT8 is compatible with WINED3DVIEWPORT */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetViewport(This->WineD3DDevice, (WINED3DVIEWPORT *)pViewport); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1136,9 +1214,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DMATERIAL8 is compatible with WINED3DMATERIAL */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetMaterial(This->WineD3DDevice, (const WINED3DMATERIAL *)pMaterial); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1148,9 +1227,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, TRACE("(%p) Relay\n" , This); /* Note: D3DMATERIAL8 is compatible with WINED3DMATERIAL */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetMaterial(This->WineD3DDevice, (WINED3DMATERIAL *)pMaterial); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1158,11 +1238,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWO IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - + /* Note: D3DLIGHT8 is compatible with WINED3DLIGHT */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetLight(This->WineD3DDevice, Index, (const WINED3DLIGHT *)pLight); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1172,9 +1253,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWO TRACE("(%p) Relay\n" , This); /* Note: D3DLIGHT8 is compatible with WINED3DLIGHT */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetLight(This->WineD3DDevice, Index, (WINED3DLIGHT *)pLight); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1183,9 +1265,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetLightEnable(This->WineD3DDevice, Index, Enable); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1194,9 +1277,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 ifac HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetLightEnable(This->WineD3DDevice, Index, pEnable); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1205,9 +1289,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetClipPlane(This->WineD3DDevice, Index, pPlane); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1216,9 +1301,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetClipPlane(This->WineD3DDevice, Index, pPlane); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1227,9 +1313,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 ifac HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetRenderState(This->WineD3DDevice, State, Value); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1238,9 +1325,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 ifac HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetRenderState(This->WineD3DDevice, State, pValue); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1249,9 +1337,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 ifa HRESULT hr; TRACE("(%p)\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_BeginStateBlock(This->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1266,11 +1355,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface /* Tell wineD3D to endstateblock before anything else (in case we run out * of memory later and cause locking problems) */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_EndStateBlock(This->WineD3DDevice , &wineD3DStateBlock); if (hr != D3D_OK) { WARN("IWineD3DDevice_EndStateBlock returned an error\n"); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -1281,8 +1370,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface object->wineD3DStateBlock = wineD3DStateBlock; - *pToken = d3d8_allocate_handle(&This->handle_table, object); - LeaveCriticalSection(&d3d8_cs); + *pToken = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_SB); + wined3d_mutex_unlock(); if (*pToken == D3D8_INVALID_HANDLE) { @@ -1304,16 +1393,17 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 ifa TRACE("(%p) %#x Relay\n", This, Token); - EnterCriticalSection(&d3d8_cs); - pSB = d3d8_get_object(&This->handle_table, Token - 1); + wined3d_mutex_lock(); + pSB = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB); if (!pSB) { WARN("Invalid handle (%#x) passed.\n", Token); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return D3DERR_INVALIDCALL; } hr = IWineD3DStateBlock_Apply(pSB->wineD3DStateBlock); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1324,16 +1414,17 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 i TRACE("(%p) %#x Relay\n", This, Token); - EnterCriticalSection(&d3d8_cs); - pSB = d3d8_get_object(&This->handle_table, Token - 1); + wined3d_mutex_lock(); + pSB = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB); if (!pSB) { WARN("Invalid handle (%#x) passed.\n", Token); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return D3DERR_INVALIDCALL; } hr = IWineD3DStateBlock_Capture(pSB->wineD3DStateBlock); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1343,9 +1434,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 if TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); - pSB = d3d8_free_handle(&This->handle_table, Token - 1); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); + pSB = d3d8_free_handle(&This->handle_table, Token - 1, D3D8_HANDLE_SB); + wined3d_mutex_unlock(); if (!pSB) { @@ -1388,19 +1479,19 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(IDirect3DDevice8 *if object->lpVtbl = &Direct3DStateBlock8_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateStateBlock(This->WineD3DDevice, (WINED3DSTATEBLOCKTYPE)Type, &object->wineD3DStateBlock, (IUnknown *)object); if (FAILED(hr)) { - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); ERR("IWineD3DDevice_CreateStateBlock failed, hr %#x\n", hr); HeapFree(GetProcessHeap(), 0, object); return hr; } - *handle = d3d8_allocate_handle(&This->handle_table, object); - LeaveCriticalSection(&d3d8_cs); + *handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_SB); + wined3d_mutex_unlock(); if (*handle == D3D8_INVALID_HANDLE) { @@ -1420,9 +1511,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface HRESULT hr; TRACE("(%p) Relay\n" , This); /* FIXME: Verify that D3DCLIPSTATUS8 ~= WINED3DCLIPSTATUS */ - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_SetClipStatus(This->WineD3DDevice, (const WINED3DCLIPSTATUS *)pClipStatus); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1431,9 +1524,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetClipStatus(This->WineD3DDevice, (WINED3DCLIPSTATUS *)pClipStatus); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1448,7 +1542,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, D return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, &retTexture); if (rc == D3D_OK && NULL != retTexture) { IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); @@ -1457,7 +1551,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, D FIXME("Call to get texture (%d) failed (%p)\n", Stage, retTexture); *ppTexture = NULL; } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return rc; } @@ -1467,10 +1561,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, D HRESULT hr; TRACE("(%p) Relay %d %p\n" , This, Stage, pTexture); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTexture(This->WineD3DDevice, Stage, pTexture==NULL ? NULL : ((IDirect3DBaseTexture8Impl *)pTexture)->wineD3DBaseTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1518,12 +1613,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); - + wined3d_mutex_lock(); if (l->sampler_state) hr = IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Stage, l->state, pValue); else hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, l->state, pValue); + wined3d_mutex_unlock(); - LeaveCriticalSection(&d3d8_cs); return hr; } @@ -1533,12 +1627,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); - + wined3d_mutex_lock(); if (l->sampler_state) hr = IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Stage, l->state, Value); else hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, l->state, Value); + wined3d_mutex_unlock(); - LeaveCriticalSection(&d3d8_cs); return hr; } @@ -1547,9 +1640,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 ifac HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_ValidateDevice(This->WineD3DDevice, pNumPasses); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1564,9 +1658,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1575,9 +1670,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1586,9 +1682,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDE HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1597,22 +1694,26 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3D HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { - IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; +static HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(IDirect3DDevice8 *iface, D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, UINT PrimitiveCount) +{ + IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawPrimitive(This->WineD3DDevice, StartVertex, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount)); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1622,11 +1723,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawIndexedPrimitive(This->WineD3DDevice, MinVertexIndex, NumVertices, startIndex, vertex_count_from_primitive_count(PrimitiveType, primCount)); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1635,12 +1737,13 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 ifa HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawPrimitiveUP(This->WineD3DDevice, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pVertexStreamZeroData, VertexStreamZeroStride); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1652,12 +1755,13 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->WineD3DDevice, MinVertexIndex, NumVertexIndices, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pIndexData, wined3dformat_from_d3dformat(IndexDataFormat), pVertexStreamZeroData, VertexStreamZeroStride); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1667,9 +1771,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 ifa IDirect3DVertexBuffer8Impl *dest = (IDirect3DVertexBuffer8Impl *) pDestBuffer; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_ProcessVertices(This->WineD3DDevice,SrcStartIndex, DestIndex, VertexCount, dest->wineD3DVertexBuffer, NULL, Flags, dest->fvf); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1704,10 +1809,11 @@ static HRESULT IDirect3DDevice8Impl_CreateVertexDeclaration(IDirect3DDevice8 *if CopyMemory(object->elements, declaration, object->elements_size); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateVertexDeclaration(This->WineD3DDevice, &object->wined3d_vertex_declaration, (IUnknown *)object, wined3d_elements, wined3d_element_count); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, wined3d_elements); if (FAILED(hr)) { @@ -1726,7 +1832,6 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; HRESULT hrc = D3D_OK; IDirect3DVertexShader8Impl *object; - IWineD3DVertexDeclaration *wined3d_vertex_declaration; const DWORD *token = pDeclaration; DWORD handle; @@ -1766,12 +1871,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); - handle = d3d8_allocate_handle(&This->handle_table, object); + wined3d_mutex_lock(); + handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_VS); if (handle == D3D8_INVALID_HANDLE) { ERR("Failed to allocate shader handle\n"); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); IDirect3DVertexDeclaration8_Release(object->vertex_declaration); HeapFree(GetProcessHeap(), 0, object); *ppShader = 0; @@ -1783,19 +1888,17 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 *ppShader = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->shader_handle = shader_handle; } - wined3d_vertex_declaration = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->wined3d_vertex_declaration; - if (pFunction) { /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */ - hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, wined3d_vertex_declaration, - pFunction, &object->wineD3DVertexShader, (IUnknown *)object); + hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, pFunction, + NULL /* output signature */, &object->wineD3DVertexShader, (IUnknown *)object); if (FAILED(hrc)) { /* free up object */ FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n"); - d3d8_free_handle(&This->handle_table, handle); + d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_VS); IDirect3DVertexDeclaration8_Release(object->vertex_declaration); HeapFree(GetProcessHeap(), 0, object); *ppShader = 0; @@ -1807,7 +1910,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 } } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hrc; } @@ -1891,29 +1994,31 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa if (VS_HIGHESTFIXEDFXF >= pShader) { TRACE("Setting FVF, %#x\n", pShader); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, IDirect3DDevice8Impl_FindDecl(This, pShader)->wined3d_vertex_declaration); IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3D_OK; } TRACE("Setting shader\n"); - EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + wined3d_mutex_lock(); + shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; } hr = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration); if (SUCCEEDED(hr)) hr = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, shader->wineD3DVertexShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); TRACE("Returning hr %#x\n", hr); @@ -1927,12 +2032,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 ifa HRESULT hrc; TRACE("(%p) : Relay device@%p\n", This, This->WineD3DDevice); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetVertexDeclaration(This->WineD3DDevice, &wined3d_declaration); if (FAILED(hrc)) { - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); WARN("(%p) : Call to IWineD3DDevice_GetVertexDeclaration failed %#x (device %p)\n", This, hrc, This->WineD3DDevice); return hrc; @@ -1940,14 +2045,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 ifa if (!wined3d_declaration) { - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); *ppShader = 0; return D3D_OK; } hrc = IWineD3DVertexDeclaration_GetParent(wined3d_declaration, (IUnknown **)&d3d8_declaration); IWineD3DVertexDeclaration_Release(wined3d_declaration); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hrc)) { *ppShader = ((IDirect3DVertexDeclaration8Impl *)d3d8_declaration)->shader_handle; @@ -1966,13 +2071,13 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE TRACE("(%p) : pShader %#x\n", This, pShader); - EnterCriticalSection(&d3d8_cs); - - shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + wined3d_mutex_lock(); + shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; } @@ -1984,7 +2089,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE IWineD3DVertexShader_Release(cur); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (IUnknown_Release((IUnknown *)shader)) { @@ -2005,9 +2110,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEV return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2022,9 +2128,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEV return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2035,10 +2142,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3D TRACE("(%p) : pVertexShader 0x%08x, pData %p, *pSizeOfData %u\n", This, pVertexShader, pData, *pSizeOfData); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); + shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); + wined3d_mutex_unlock(); - shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1)); - LeaveCriticalSection(&d3d8_cs); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pVertexShader); @@ -2071,26 +2178,26 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEV TRACE("(%p) : pVertexShader %#x, pData %p, pSizeOfData %p\n", This, pVertexShader, pData, pSizeOfData); - EnterCriticalSection(&d3d8_cs); - - shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1)); + wined3d_mutex_lock(); + shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pVertexShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; } if (!shader->wineD3DVertexShader) { - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); *pSizeOfData = 0; return D3D_OK; } hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData); + wined3d_mutex_unlock(); - LeaveCriticalSection(&d3d8_cs); return hr; } @@ -2100,18 +2207,19 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, I IDirect3DIndexBuffer8Impl *ib = (IDirect3DIndexBuffer8Impl *)pIndexData; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large * vertex buffers can't be created to address them with an index that requires the 32nd bit * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least * problem) */ + wined3d_mutex_lock(); IWineD3DDevice_SetBaseVertexIndex(This->WineD3DDevice, baseVertexIndex); hr = IWineD3DDevice_SetIndices(This->WineD3DDevice, ib ? ib->wineD3DIndexBuffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2126,8 +2234,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, I return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); /* The case from UINT to INT is safe because d3d8 will never set negative values */ + wined3d_mutex_lock(); IWineD3DDevice_GetBaseVertexIndex(This->WineD3DDevice, (INT *) pBaseVertexIndex); rc = IWineD3DDevice_GetIndices(This->WineD3DDevice, &retIndexData); if (SUCCEEDED(rc) && retIndexData) { @@ -2137,7 +2245,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, I if (FAILED(rc)) FIXME("Call to GetIndices failed\n"); *ppIndexData = NULL; } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return rc; } @@ -2164,20 +2272,21 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 i object->ref = 1; object->lpVtbl = &Direct3DPixelShader8_Vtbl; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, NULL, &object->wineD3DPixelShader, (IUnknown *)object); if (FAILED(hr)) { - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); FIXME("(%p) call to IWineD3DDevice_CreatePixelShader failed\n", This); HeapFree(GetProcessHeap(), 0 , object); *ppShader = 0; return hr; } - handle = d3d8_allocate_handle(&This->handle_table, object); - LeaveCriticalSection(&d3d8_cs); + handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_PS); + wined3d_mutex_unlock(); + if (handle == D3D8_INVALID_HANDLE) { ERR("Failed to allocate shader handle\n"); @@ -2198,26 +2307,27 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 ifac TRACE("(%p) : pShader %#x\n", This, pShader); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); if (!pShader) { hr = IWineD3DDevice_SetPixelShader(This->WineD3DDevice, NULL); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } - shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return D3DERR_INVALIDCALL; } TRACE("(%p) : Setting shader %p\n", This, shader); hr = IWineD3DDevice_SetPixelShader(This->WineD3DDevice, shader->wineD3DPixelShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2232,7 +2342,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 ifac return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetPixelShader(This->WineD3DDevice, &object); if (D3D_OK == hrc && NULL != object) { IDirect3DPixelShader8Impl *d3d8_shader; @@ -2243,9 +2353,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 ifac } else { *ppShader = 0; } + wined3d_mutex_unlock(); TRACE("(%p) : returning %#x\n", This, *ppShader); - LeaveCriticalSection(&d3d8_cs); + return hrc; } @@ -2256,14 +2367,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 i TRACE("(%p) : pShader %#x\n", This, pShader); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); - shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); - LeaveCriticalSection(&d3d8_cs); - return D3DERR_INVALIDCALL; + wined3d_mutex_unlock(); + return D3D_OK; } IWineD3DDevice_GetPixelShader(This->WineD3DDevice, &cur); @@ -2274,7 +2385,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 i IWineD3DPixelShader_Release(cur); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (IUnknown_Release((IUnknown *)shader)) { @@ -2289,9 +2400,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2300,9 +2412,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2313,17 +2426,19 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVI TRACE("(%p) : pPixelShader %#x, pData %p, pSizeOfData %p\n", This, pPixelShader, pData, pSizeOfData); - EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pPixelShader - (VS_HIGHESTFIXEDFXF + 1)); + wined3d_mutex_lock(); + shader = d3d8_get_object(&This->handle_table, pPixelShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pPixelShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; } hr = IWineD3DPixelShader_GetFunction(shader->wineD3DPixelShader, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2332,9 +2447,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DrawRectPatch(This->WineD3DDevice, Handle, pNumSegs, (CONST WINED3DRECTPATCH_INFO *)pRectPatchInfo); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2343,9 +2459,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DrawTriPatch(This->WineD3DDevice, Handle, pNumSegs, (CONST WINED3DTRIPATCH_INFO *)pTriPatchInfo); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2354,9 +2471,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DeletePatch(This->WineD3DDevice, Handle); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2365,11 +2483,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 ifa HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetStreamSource(This->WineD3DDevice, StreamNumber, NULL == pStreamData ? NULL : ((IDirect3DVertexBuffer8Impl *)pStreamData)->wineD3DVertexBuffer, 0/* Offset in bytes */, Stride); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -2384,7 +2503,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 ifa return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, &retStream, 0 /* Offset in bytes */, pStride); if (rc == D3D_OK && NULL != retStream) { IWineD3DBuffer_GetParent(retStream, (IUnknown **)pStream); @@ -2395,7 +2514,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 ifa } *pStream = NULL; } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return rc; } @@ -2564,8 +2683,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen hr = IDirect3DDevice8Impl_CreateSurface((IDirect3DDevice8 *)This, width, height, d3dformat_from_wined3dformat(format), lockable, FALSE /* Discard */, level, - (IDirect3DSurface8 **)&d3d_surface, D3DRTYPE_SURFACE, usage, pool, - D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */); + (IDirect3DSurface8 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */); if (FAILED(hr)) { ERR("(%p) CreateSurface failed, returning %#x\n", iface, hr); diff --git a/reactos/dll/directx/wine/d3d8/directx.c b/reactos/dll/directx/wine/d3d8/directx.c index d39d3d64768..3368794d732 100644 --- a/reactos/dll/directx/wine/d3d8/directx.c +++ b/reactos/dll/directx/wine/d3d8/directx.c @@ -71,9 +71,11 @@ static ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) { if (ref == 0) { TRACE("Releasing wined3d %p\n", This->WineD3D); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); IWineD3D_Release(This->WineD3D); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } @@ -86,9 +88,10 @@ static HRESULT WINAPI IDirect3D8Impl_RegisterSoftwareDevice (LPDIRECT3D8 iface, HRESULT hr; TRACE("(%p)->(%p)\n", This, pInitializeFunction); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_RegisterSoftwareDevice(This->WineD3D, pInitializeFunction); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -97,36 +100,41 @@ static UINT WINAPI IDirect3D8Impl_GetAdapterCount (LPDIRECT3D8 iface) { HRESULT hr; TRACE("(%p)\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterCount(This->WineD3D); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D8Impl_GetAdapterIdentifier (LPDIRECT3D8 iface, - UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) { +static HRESULT WINAPI IDirect3D8Impl_GetAdapterIdentifier(LPDIRECT3D8 iface, + UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8 *pIdentifier) +{ IDirect3D8Impl *This = (IDirect3D8Impl *)iface; WINED3DADAPTER_IDENTIFIER adapter_id; HRESULT hr; TRACE("(%p)->(%d,%08x, %p\n", This, Adapter, Flags, pIdentifier); - EnterCriticalSection(&d3d8_cs); - /* dx8 and dx9 have different structures to be filled in, with incompatible - layouts so pass in pointers to the places to be filled via an internal - structure */ - adapter_id.Driver = pIdentifier->Driver; - adapter_id.Description = pIdentifier->Description; - adapter_id.DeviceName = NULL; /* d3d9 only */ - adapter_id.DriverVersion = &pIdentifier->DriverVersion; - adapter_id.VendorId = &pIdentifier->VendorId; - adapter_id.DeviceId = &pIdentifier->DeviceId; - adapter_id.SubSysId = &pIdentifier->SubSysId; - adapter_id.Revision = &pIdentifier->Revision; - adapter_id.DeviceIdentifier = &pIdentifier->DeviceIdentifier; - adapter_id.WHQLLevel = &pIdentifier->WHQLLevel; + adapter_id.driver = pIdentifier->Driver; + adapter_id.driver_size = sizeof(pIdentifier->Driver); + adapter_id.description = pIdentifier->Description; + adapter_id.description_size = sizeof(pIdentifier->Description); + adapter_id.device_name = NULL; /* d3d9 only */ + adapter_id.device_name_size = 0; /* d3d9 only */ + + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterIdentifier(This->WineD3D, Adapter, Flags, &adapter_id); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + + pIdentifier->DriverVersion = adapter_id.driver_version; + pIdentifier->VendorId = adapter_id.vendor_id; + pIdentifier->DeviceId = adapter_id.device_id; + pIdentifier->SubSysId = adapter_id.subsystem_id; + pIdentifier->Revision = adapter_id.revision; + memcpy(&pIdentifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(pIdentifier->DeviceIdentifier)); + pIdentifier->WHQLLevel = adapter_id.whql_level; + return hr; } @@ -135,9 +143,10 @@ static UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface,UINT Ad HRESULT hr; TRACE("(%p)->(%d)\n", This, Adapter); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterModeCount(This->WineD3D, Adapter, 0 /* format */); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -146,9 +155,9 @@ static HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface, UINT A HRESULT hr; TRACE("(%p)->(%d, %d, %p)\n", This, Adapter, Mode, pMode); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, WINED3DFMT_UNKNOWN, Mode, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -160,9 +169,9 @@ static HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface, U HRESULT hr; TRACE("(%p)->(%d,%p)\n", This, Adapter, pMode); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -176,10 +185,11 @@ static HRESULT WINAPI IDirect3D8Impl_CheckDeviceType (LPDIRECT3D8 i HRESULT hr; TRACE("(%p)->(%d, %d, %d, %d, %s)\n", This, Adapter, CheckType, DisplayFormat, BackBufferFormat, Windowed ? "true" : "false"); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceType(This->WineD3D, Adapter, CheckType, wined3dformat_from_d3dformat(DisplayFormat), wined3dformat_from_d3dformat(BackBufferFormat), Windowed); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -191,6 +201,14 @@ static HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 i WINED3DRESOURCETYPE WineD3DRType; TRACE("(%p)->(%d, %d, %d, %08x, %d, %d)\n", This, Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat); + if(CheckFormat == D3DFMT_R8G8B8) + { + /* See comment in dlls/d3d9/directx.c, IDirect3D9Impl_CheckDeviceFormat for details */ + WARN("D3DFMT_R8G8B8 is not available on windows, returning D3DERR_NOTAVAILABLE\n"); + return D3DERR_NOTAVAILABLE; + } + + switch(RType) { case D3DRTYPE_VERTEXBUFFER: case D3DRTYPE_INDEXBUFFER: @@ -202,42 +220,59 @@ static HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 i break; } - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(AdapterFormat), Usage, WineD3DRType, wined3dformat_from_d3dformat(CheckFormat), SURFACE_OPENGL); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D8Impl_CheckDeviceMultiSampleType(LPDIRECT3D8 iface, - UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, - BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) { +static HRESULT WINAPI IDirect3D8Impl_CheckDeviceMultiSampleType(IDirect3D8 *iface, UINT Adapter, + D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) +{ IDirect3D8Impl *This = (IDirect3D8Impl *)iface; HRESULT hr; TRACE("(%p)-<(%d, %d, %d, %s, %d)\n", This, Adapter, DeviceType, SurfaceFormat, Windowed ? "true" : "false", MultiSampleType); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceMultiSampleType(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(SurfaceFormat), Windowed, (WINED3DMULTISAMPLE_TYPE) MultiSampleType, NULL); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D8Impl_CheckDepthStencilMatch(LPDIRECT3D8 iface, - UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, - D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { +static HRESULT WINAPI IDirect3D8Impl_CheckDepthStencilMatch(IDirect3D8 *iface, UINT Adapter, D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) +{ IDirect3D8Impl *This = (IDirect3D8Impl *)iface; HRESULT hr; TRACE("(%p)-<(%d, %d, %d, %d, %d)\n", This, Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDepthStencilMatch(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(AdapterFormat), wined3dformat_from_d3dformat(RenderTargetFormat), wined3dformat_from_d3dformat(DepthStencilFormat)); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } +void fixup_caps(WINED3DCAPS *caps) +{ + /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ + if (caps->PixelShaderVersion > D3DPS_VERSION(1,4)) { + caps->PixelShaderVersion = D3DPS_VERSION(1,4); + } + if (caps->VertexShaderVersion > D3DVS_VERSION(1,1)) { + caps->VertexShaderVersion = D3DVS_VERSION(1,1); + } + caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); + + caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED; +} + static HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) { IDirect3D8Impl *This = (IDirect3D8Impl *)iface; HRESULT hrc = D3D_OK; @@ -252,21 +287,15 @@ static HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Ada if(pWineCaps == NULL){ return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/ } - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, pWineCaps); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + + fixup_caps(pWineCaps); WINECAPSTOD3D8CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); - /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ - if(pCaps->PixelShaderVersion > D3DPS_VERSION(1,4)){ - pCaps->PixelShaderVersion = D3DPS_VERSION(1,4); - } - if(pCaps->VertexShaderVersion > D3DVS_VERSION(1,1)){ - pCaps->VertexShaderVersion = D3DVS_VERSION(1,1); - } - pCaps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst); - TRACE("(%p) returning %p\n", This, pCaps); return hrc; } @@ -276,9 +305,10 @@ static HMONITOR WINAPI IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT HMONITOR ret; TRACE("(%p)->(%d)\n", This, Adapter); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3D_GetAdapterMonitor(This->WineD3D, Adapter); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -344,14 +374,15 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapte *ppReturnedDeviceInterface = (IDirect3DDevice8 *)object; /* Allocate an associated WineD3DDevice object */ - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, (IUnknown *)object, (IWineD3DDeviceParent *)&object->device_parent_vtbl, &object->WineD3DDevice); if (hr != D3D_OK) { HeapFree(GetProcessHeap(), 0, object); *ppReturnedDeviceInterface = NULL; - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -378,7 +409,7 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapte } hr = IWineD3DDevice_Init3D(object->WineD3DDevice, &localParameters); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; @@ -404,9 +435,11 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapte object->decls = HeapAlloc(GetProcessHeap(), 0, object->declArraySize * sizeof(*object->decls)); if(!object->decls) { ERR("Out of memory\n"); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); IWineD3DDevice_Release(object->WineD3DDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, object); *ppReturnedDeviceInterface = NULL; hr = E_OUTOFMEMORY; diff --git a/reactos/dll/directx/wine/d3d8/indexbuffer.c b/reactos/dll/directx/wine/d3d8/indexbuffer.c index a0de5c5caf0..b59b1ab292d 100644 --- a/reactos/dll/directx/wine/d3d8/indexbuffer.c +++ b/reactos/dll/directx/wine/d3d8/indexbuffer.c @@ -56,9 +56,10 @@ static ULONG WINAPI IDirect3DIndexBuffer8Impl_Release(LPDIRECT3DINDEXBUFFER8 ifa TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DBuffer_Release(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -72,14 +73,15 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_GetDevice(LPDIRECT3DINDEXBUFFER8 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDevice(This->wineD3DIndexBuffer, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -88,9 +90,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_SetPrivateData(LPDIRECT3DINDEXBU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_SetPrivateData(This->wineD3DIndexBuffer, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -99,9 +102,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_GetPrivateData(LPDIRECT3DINDEXBU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetPrivateData(This->wineD3DIndexBuffer, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -110,9 +114,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_FreePrivateData(LPDIRECT3DINDEXB HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_FreePrivateData(This->wineD3DIndexBuffer, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -121,9 +126,10 @@ static DWORD WINAPI IDirect3DIndexBuffer8Impl_SetPriority(LPDIRECT3DINDEXBUFFER8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_SetPriority(This->wineD3DIndexBuffer, PriorityNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -132,9 +138,10 @@ static DWORD WINAPI IDirect3DIndexBuffer8Impl_GetPriority(LPDIRECT3DINDEXBUFFER8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_GetPriority(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -142,9 +149,9 @@ static void WINAPI IDirect3DIndexBuffer8Impl_PreLoad(LPDIRECT3DINDEXBUFFER8 ifac IDirect3DIndexBuffer8Impl *This = (IDirect3DIndexBuffer8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DBuffer_PreLoad(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DIndexBuffer8Impl_GetType(LPDIRECT3DINDEXBUFFER8 iface) { @@ -160,9 +167,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_Lock(LPDIRECT3DINDEXBUFFER8 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Map(This->wineD3DIndexBuffer, OffsetToLock, SizeToLock, ppbData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -171,9 +179,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_Unlock(LPDIRECT3DINDEXBUFFER8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Unmap(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -183,9 +192,9 @@ static HRESULT WINAPI IDirect3DIndexBuffer8Impl_GetDesc(LPDIRECT3DINDEXBUFFER8 i WINED3DBUFFER_DESC desc; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDesc(This->wineD3DIndexBuffer, &desc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) { pDesc->Format = d3dformat_from_wined3dformat(This->format); diff --git a/reactos/dll/directx/wine/d3d8/pixelshader.c b/reactos/dll/directx/wine/d3d8/pixelshader.c index ae8d15fa63f..2f0fb1c4c32 100644 --- a/reactos/dll/directx/wine/d3d8/pixelshader.c +++ b/reactos/dll/directx/wine/d3d8/pixelshader.c @@ -56,9 +56,10 @@ static ULONG WINAPI IDirect3DPixelShader8Impl_Release(IDirect3DPixelShader8 * if TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DPixelShader_Release(This->wineD3DPixelShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } return ref; diff --git a/reactos/dll/directx/wine/d3d8/stateblock.c b/reactos/dll/directx/wine/d3d8/stateblock.c index ace9211e0a9..04c4e484826 100644 --- a/reactos/dll/directx/wine/d3d8/stateblock.c +++ b/reactos/dll/directx/wine/d3d8/stateblock.c @@ -58,9 +58,10 @@ static ULONG WINAPI IDirect3DStateBlock8Impl_Release(IDirect3DStateBlock8 *iface TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DStateBlock_Release(This->wineD3DStateBlock); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -74,16 +75,14 @@ static HRESULT WINAPI IDirect3DStateBlock8Impl_GetDevice(IDirect3DStateBlock8 *i TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); - + wined3d_mutex_lock(); hr = IWineD3DStateBlock_GetDevice(This->wineD3DStateBlock, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -94,11 +93,9 @@ static HRESULT WINAPI IDirect3DStateBlock8Impl_Capture(IDirect3DStateBlock8 *ifa TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); - + wined3d_mutex_lock(); hr = IWineD3DStateBlock_Capture(This->wineD3DStateBlock); - - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } @@ -109,11 +106,9 @@ static HRESULT WINAPI IDirect3DStateBlock8Impl_Apply(IDirect3DStateBlock8 *iface TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); - + wined3d_mutex_lock(); hr = IWineD3DStateBlock_Apply(This->wineD3DStateBlock); - - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); return hr; } diff --git a/reactos/dll/directx/wine/d3d8/surface.c b/reactos/dll/directx/wine/d3d8/surface.c index 4b382ecbc98..3185a1f88ac 100644 --- a/reactos/dll/directx/wine/d3d8/surface.c +++ b/reactos/dll/directx/wine/d3d8/surface.c @@ -76,9 +76,10 @@ static ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) { if (This->parentDevice) IUnknown_Release(This->parentDevice); /* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */ if (!This->isImplicit) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DSurface_Release(This->wineD3DSurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } } @@ -94,14 +95,15 @@ static HRESULT WINAPI IDirect3DSurface8Impl_GetDevice(LPDIRECT3DSURFACE8 iface, HRESULT hr; TRACE("(%p)->(%p)\n", This, ppDevice); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetDevice(This->wineD3DSurface, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -110,9 +112,10 @@ static HRESULT WINAPI IDirect3DSurface8Impl_SetPrivateData(LPDIRECT3DSURFACE8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_SetPrivateData(This->wineD3DSurface, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -121,9 +124,10 @@ static HRESULT WINAPI IDirect3DSurface8Impl_GetPrivateData(LPDIRECT3DSURFACE8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetPrivateData(This->wineD3DSurface, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -132,9 +136,10 @@ static HRESULT WINAPI IDirect3DSurface8Impl_FreePrivateData(LPDIRECT3DSURFACE8 i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_FreePrivateData(This->wineD3DSurface, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -159,22 +164,21 @@ static HRESULT WINAPI IDirect3DSurface8Impl_GetDesc(LPDIRECT3DSURFACE8 iface, D3 HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - memset(&wined3ddesc, 0, sizeof(wined3ddesc)); - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetDesc(This->wineD3DSurface, &wined3ddesc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -185,7 +189,7 @@ static HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D TRACE("(%p) Relay\n", This); TRACE("(%p) calling IWineD3DSurface_LockRect %p %p %p %d\n", This, This->wineD3DSurface, pLockedRect, pRect, Flags); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); if (pRect) { D3DSURFACE_DESC desc; IDirect3DSurface8_GetDesc(iface, &desc); @@ -197,13 +201,15 @@ static HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D || (pRect->right > desc.Width) || (pRect->bottom > desc.Height)) { WARN("Trying to lock an invalid rectangle, returning D3DERR_INVALIDCALL\n"); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; } } hr = IWineD3DSurface_LockRect(This->wineD3DSurface, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -212,9 +218,10 @@ static HRESULT WINAPI IDirect3DSurface8Impl_UnlockRect(LPDIRECT3DSURFACE8 iface) HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_UnlockRect(This->wineD3DSurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + switch(hr) { case WINEDDERR_NOTLOCKED: return D3DERR_INVALIDCALL; diff --git a/reactos/dll/directx/wine/d3d8/swapchain.c b/reactos/dll/directx/wine/d3d8/swapchain.c index 25d2a0ee346..67f3429cad6 100644 --- a/reactos/dll/directx/wine/d3d8/swapchain.c +++ b/reactos/dll/directx/wine/d3d8/swapchain.c @@ -56,9 +56,10 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_Release(LPDIRECT3DSWAPCHAIN8 iface) TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D8CB_DestroyRenderTarget); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + if (This->parentDevice) IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -71,9 +72,10 @@ static HRESULT WINAPI IDirect3DSwapChain8Impl_Present(LPDIRECT3DSWAPCHAIN8 iface HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_Present(This->wineD3DSwapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -84,13 +86,14 @@ static HRESULT WINAPI IDirect3DSwapChain8Impl_GetBackBuffer(LPDIRECT3DSWAPCHAIN8 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DSwapChain_GetBackBuffer(This->wineD3DSwapChain, iBackBuffer, (WINED3DBACKBUFFER_TYPE )Type, &mySurface); if (hrc == D3D_OK && NULL != mySurface) { IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppBackBuffer); IWineD3DSurface_Release(mySurface); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hrc; } diff --git a/reactos/dll/directx/wine/d3d8/texture.c b/reactos/dll/directx/wine/d3d8/texture.c index c1bb91ece65..c22c49111b8 100644 --- a/reactos/dll/directx/wine/d3d8/texture.c +++ b/reactos/dll/directx/wine/d3d8/texture.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DTexture_Destroy(This->wineD3DTexture, D3D8CB_DestroySurface); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -72,14 +73,16 @@ static HRESULT WINAPI IDirect3DTexture8Impl_GetDevice(LPDIRECT3DTEXTURE8 iface, IWineD3DDevice *wined3d_device; HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hr = IWineD3DTexture_GetDevice(This->wineD3DTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -88,9 +91,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_SetPrivateData(LPDIRECT3DTEXTURE8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_SetPrivateData(This->wineD3DTexture, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -99,9 +103,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_GetPrivateData(LPDIRECT3DTEXTURE8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_GetPrivateData(This->wineD3DTexture, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -110,9 +115,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_FreePrivateData(LPDIRECT3DTEXTURE8 i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_FreePrivateData(This->wineD3DTexture, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -121,9 +127,10 @@ static DWORD WINAPI IDirect3DTexture8Impl_SetPriority(LPDIRECT3DTEXTURE8 iface, DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_SetPriority(This->wineD3DTexture, PriorityNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -132,9 +139,10 @@ static DWORD WINAPI IDirect3DTexture8Impl_GetPriority(LPDIRECT3DTEXTURE8 iface) DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetPriority(This->wineD3DTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -142,9 +150,9 @@ static void WINAPI IDirect3DTexture8Impl_PreLoad(LPDIRECT3DTEXTURE8 iface) { IDirect3DTexture8Impl *This = (IDirect3DTexture8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DTexture_PreLoad(This->wineD3DTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DTexture8Impl_GetType(LPDIRECT3DTEXTURE8 iface) { @@ -152,9 +160,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DTexture8Impl_GetType(LPDIRECT3DTEXTURE8 i D3DRESOURCETYPE type; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); type = IWineD3DTexture_GetType(This->wineD3DTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return type; } @@ -164,9 +173,10 @@ static DWORD WINAPI IDirect3DTexture8Impl_SetLOD(LPDIRECT3DTEXTURE8 iface, DWORD DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_SetLOD(This->wineD3DTexture, LODNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -175,9 +185,10 @@ static DWORD WINAPI IDirect3DTexture8Impl_GetLOD(LPDIRECT3DTEXTURE8 iface) { DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetLOD(This->wineD3DTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -186,9 +197,10 @@ static DWORD WINAPI IDirect3DTexture8Impl_GetLevelCount(LPDIRECT3DTEXTURE8 iface DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetLevelCount(This->wineD3DTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -200,22 +212,21 @@ static HRESULT WINAPI IDirect3DTexture8Impl_GetLevelDesc(LPDIRECT3DTEXTURE8 ifac WINED3DSURFACE_DESC wined3ddesc; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - memset(&wined3ddesc, 0, sizeof(wined3ddesc)); - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -226,13 +237,15 @@ static HRESULT WINAPI IDirect3DTexture8Impl_GetSurfaceLevel(LPDIRECT3DTEXTURE8 i IWineD3DSurface *mySurface = NULL; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + + wined3d_mutex_lock(); hrc = IWineD3DTexture_GetSurfaceLevel(This->wineD3DTexture, Level, &mySurface); if (hrc == D3D_OK && NULL != ppSurfaceLevel) { IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppSurfaceLevel); IWineD3DSurface_Release(mySurface); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -241,9 +254,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_LockRect(LPDIRECT3DTEXTURE8 iface, U HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_LockRect(This->wineD3DTexture, Level, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -252,9 +266,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_UnlockRect(LPDIRECT3DTEXTURE8 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_UnlockRect(This->wineD3DTexture, Level); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -263,9 +278,10 @@ static HRESULT WINAPI IDirect3DTexture8Impl_AddDirtyRect(LPDIRECT3DTEXTURE8 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_AddDirtyRect(This->wineD3DTexture, pDirtyRect); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d8/vertexbuffer.c b/reactos/dll/directx/wine/d3d8/vertexbuffer.c index a282cda6bf2..617aff3529a 100644 --- a/reactos/dll/directx/wine/d3d8/vertexbuffer.c +++ b/reactos/dll/directx/wine/d3d8/vertexbuffer.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DVertexBuffer8Impl_Release(LPDIRECT3DVERTEXBUFFER8 i TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DBuffer_Release(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -74,14 +75,15 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_GetDevice(LPDIRECT3DVERTEXBUFFE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDevice(This->wineD3DVertexBuffer, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -90,9 +92,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_SetPrivateData(LPDIRECT3DVERTEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_SetPrivateData(This->wineD3DVertexBuffer, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -101,9 +104,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_GetPrivateData(LPDIRECT3DVERTEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetPrivateData(This->wineD3DVertexBuffer, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -112,9 +116,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_FreePrivateData(LPDIRECT3DVERTE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_FreePrivateData(This->wineD3DVertexBuffer, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -123,9 +128,10 @@ static DWORD WINAPI IDirect3DVertexBuffer8Impl_SetPriority(LPDIRECT3DVERTEXBUFFE DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_SetPriority(This->wineD3DVertexBuffer, PriorityNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -134,9 +140,10 @@ static DWORD WINAPI IDirect3DVertexBuffer8Impl_GetPriority(LPDIRECT3DVERTEXBUFFE DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_GetPriority(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -144,9 +151,9 @@ static void WINAPI IDirect3DVertexBuffer8Impl_PreLoad(LPDIRECT3DVERTEXBUFFER8 if IDirect3DVertexBuffer8Impl *This = (IDirect3DVertexBuffer8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DBuffer_PreLoad(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DVertexBuffer8Impl_GetType(LPDIRECT3DVERTEXBUFFER8 iface) { @@ -162,9 +169,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_Lock(LPDIRECT3DVERTEXBUFFER8 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Map(This->wineD3DVertexBuffer, OffsetToLock, SizeToLock, ppbData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -173,9 +181,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_Unlock(LPDIRECT3DVERTEXBUFFER8 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Unmap(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -185,9 +194,9 @@ static HRESULT WINAPI IDirect3DVertexBuffer8Impl_GetDesc(LPDIRECT3DVERTEXBUFFER8 WINED3DBUFFER_DESC desc; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDesc(This->wineD3DVertexBuffer, &desc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) { pDesc->Type = D3DRTYPE_VERTEXBUFFER; diff --git a/reactos/dll/directx/wine/d3d8/vertexdeclaration.c b/reactos/dll/directx/wine/d3d8/vertexdeclaration.c index e9d56d09fbc..2eea098a4e5 100644 --- a/reactos/dll/directx/wine/d3d8/vertexdeclaration.c +++ b/reactos/dll/directx/wine/d3d8/vertexdeclaration.c @@ -61,9 +61,10 @@ static ULONG WINAPI IDirect3DVertexDeclaration8Impl_Release(IDirect3DVertexDecla TRACE("(%p) : Releasing to %d\n", This, ref_count); if (!ref_count) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVertexDeclaration_Release(This->wined3d_vertex_declaration); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This->elements); HeapFree(GetProcessHeap(), 0, This); } diff --git a/reactos/dll/directx/wine/d3d8/vertexshader.c b/reactos/dll/directx/wine/d3d8/vertexshader.c index 4ea8b52ac29..1a9b5ea9535 100644 --- a/reactos/dll/directx/wine/d3d8/vertexshader.c +++ b/reactos/dll/directx/wine/d3d8/vertexshader.c @@ -59,9 +59,9 @@ static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *i IDirect3DVertexDeclaration8_Release(This->vertex_declaration); if (This->wineD3DVertexShader) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVertexShader_Release(This->wineD3DVertexShader); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } HeapFree(GetProcessHeap(), 0, This); } diff --git a/reactos/dll/directx/wine/d3d8/volume.c b/reactos/dll/directx/wine/d3d8/volume.c index 474aad86230..968b5348a87 100644 --- a/reactos/dll/directx/wine/d3d8/volume.c +++ b/reactos/dll/directx/wine/d3d8/volume.c @@ -72,9 +72,10 @@ static ULONG WINAPI IDirect3DVolume8Impl_Release(LPDIRECT3DVOLUME8 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVolume_Release(This->wineD3DVolume); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } @@ -87,11 +88,12 @@ static HRESULT WINAPI IDirect3DVolume8Impl_GetDevice(LPDIRECT3DVOLUME8 iface, ID IDirect3DVolume8Impl *This = (IDirect3DVolume8Impl *)iface; IWineD3DDevice *myDevice = NULL; - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVolume_GetDevice(This->wineD3DVolume, &myDevice); IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); IWineD3DDevice_Release(myDevice); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return D3D_OK; } @@ -100,9 +102,10 @@ static HRESULT WINAPI IDirect3DVolume8Impl_SetPrivateData(LPDIRECT3DVOLUME8 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_SetPrivateData(This->wineD3DVolume, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -111,9 +114,10 @@ static HRESULT WINAPI IDirect3DVolume8Impl_GetPrivateData(LPDIRECT3DVOLUME8 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_GetPrivateData(This->wineD3DVolume, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -122,9 +126,10 @@ static HRESULT WINAPI IDirect3DVolume8Impl_FreePrivateData(LPDIRECT3DVOLUME8 ifa HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_FreePrivateData(This->wineD3DVolume, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -154,21 +159,21 @@ static HRESULT WINAPI IDirect3DVolume8Impl_GetDesc(LPDIRECT3DVOLUME8 iface, D3DV TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - wined3ddesc.Depth = &pDesc->Depth; - - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_GetDesc(This->wineD3DVolume, &wined3ddesc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.Format); + pDesc->Type = wined3ddesc.Type; + pDesc->Usage = wined3ddesc.Usage; + pDesc->Pool = wined3ddesc.Pool; + pDesc->Size = wined3ddesc.Size; + pDesc->Width = wined3ddesc.Width; + pDesc->Height = wined3ddesc.Height; + pDesc->Depth = wined3ddesc.Depth; + } return hr; } @@ -178,9 +183,10 @@ static HRESULT WINAPI IDirect3DVolume8Impl_LockBox(LPDIRECT3DVOLUME8 iface, D3DL HRESULT hr; TRACE("(%p) relay %p %p %p %d\n", This, This->wineD3DVolume, pLockedVolume, pBox, Flags); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_LockBox(This->wineD3DVolume, (WINED3DLOCKED_BOX *) pLockedVolume, (CONST WINED3DBOX *) pBox, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -189,9 +195,10 @@ static HRESULT WINAPI IDirect3DVolume8Impl_UnlockBox(LPDIRECT3DVOLUME8 iface) { HRESULT hr; TRACE("(%p) relay %p\n", This, This->wineD3DVolume); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_UnlockBox(This->wineD3DVolume); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d8/volumetexture.c b/reactos/dll/directx/wine/d3d8/volumetexture.c index 098827aedd8..1875081a3bd 100644 --- a/reactos/dll/directx/wine/d3d8/volumetexture.c +++ b/reactos/dll/directx/wine/d3d8/volumetexture.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8 TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture, D3D8CB_DestroyVolume); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -73,14 +74,15 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetDevice(LPDIRECT3DVOLUMETEXT HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_GetDevice(This->wineD3DVolumeTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -89,9 +91,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_SetPrivateData(LPDIRECT3DVOLUM HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_SetPrivateData(This->wineD3DVolumeTexture, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -100,9 +103,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetPrivateData(LPDIRECT3DVOLUM HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_GetPrivateData(This->wineD3DVolumeTexture, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -111,9 +115,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_FreePrivateData(LPDIRECT3DVOLU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_FreePrivateData(This->wineD3DVolumeTexture, refguid); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -122,9 +127,10 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_SetPriority(LPDIRECT3DVOLUMETEXT DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DVolumeTexture_SetPriority(This->wineD3DVolumeTexture, PriorityNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -133,9 +139,10 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_GetPriority(LPDIRECT3DVOLUMETEXT DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DVolumeTexture_GetPriority(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -143,9 +150,9 @@ static void WINAPI IDirect3DVolumeTexture8Impl_PreLoad(LPDIRECT3DVOLUMETEXTURE8 IDirect3DVolumeTexture8Impl *This = (IDirect3DVolumeTexture8Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); IWineD3DVolumeTexture_PreLoad(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DVolumeTexture8Impl_GetType(LPDIRECT3DVOLUMETEXTURE8 iface) { @@ -153,9 +160,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DVolumeTexture8Impl_GetType(LPDIRECT3DVOLU D3DRESOURCETYPE type; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); type = IWineD3DVolumeTexture_GetType(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return type; } @@ -165,9 +173,10 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_SetLOD(LPDIRECT3DVOLUMETEXTURE8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DVolumeTexture_SetLOD(This->wineD3DVolumeTexture, LODNew); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -176,9 +185,10 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_GetLOD(LPDIRECT3DVOLUMETEXTURE8 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DVolumeTexture_GetLOD(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -187,9 +197,10 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_GetLevelCount(LPDIRECT3DVOLUMETE DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); ret = IWineD3DVolumeTexture_GetLevelCount(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return ret; } @@ -197,26 +208,25 @@ static DWORD WINAPI IDirect3DVolumeTexture8Impl_GetLevelCount(LPDIRECT3DVOLUMETE static HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetLevelDesc(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level, D3DVOLUME_DESC* pDesc) { IDirect3DVolumeTexture8Impl *This = (IDirect3DVolumeTexture8Impl *)iface; WINED3DVOLUME_DESC wined3ddesc; - UINT tmpInt = -1; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d8 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - wined3ddesc.Depth = &pDesc->Depth; - - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_GetLevelDesc(This->wineD3DVolumeTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.Format); + pDesc->Type = wined3ddesc.Type; + pDesc->Usage = wined3ddesc.Usage; + pDesc->Pool = wined3ddesc.Pool; + pDesc->Size = wined3ddesc.Size; + pDesc->Width = wined3ddesc.Width; + pDesc->Height = wined3ddesc.Height; + pDesc->Depth = wined3ddesc.Depth; + } return hr; } @@ -228,13 +238,14 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetVolumeLevel(LPDIRECT3DVOLUM TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hrc = IWineD3DVolumeTexture_GetVolumeLevel(This->wineD3DVolumeTexture, Level, &myVolume); if (hrc == D3D_OK && NULL != ppVolumeLevel) { IWineD3DVolumeTexture_GetParent(myVolume, (IUnknown **)ppVolumeLevel); IWineD3DVolumeTexture_Release(myVolume); } - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -243,9 +254,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_LockBox(LPDIRECT3DVOLUMETEXTUR HRESULT hr; TRACE("(%p) Relay %p %p %p %d\n", This, This->wineD3DVolumeTexture, pLockedVolume, pBox,Flags); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_LockBox(This->wineD3DVolumeTexture, Level, (WINED3DLOCKED_BOX *) pLockedVolume, (CONST WINED3DBOX *) pBox, Flags); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -254,9 +266,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_UnlockBox(LPDIRECT3DVOLUMETEXT HRESULT hr; TRACE("(%p) Relay %p %d\n", This, This->wineD3DVolumeTexture, Level); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_UnlockBox(This->wineD3DVolumeTexture, Level); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } @@ -265,9 +278,10 @@ static HRESULT WINAPI IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3DVOLUMETE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d8_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_AddDirtyBox(This->wineD3DVolumeTexture, (CONST WINED3DBOX *) pDirtyBox); - LeaveCriticalSection(&d3d8_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d9/cubetexture.c b/reactos/dll/directx/wine/d3d9/cubetexture.c index bbd171ea62a..8209d0b367f 100644 --- a/reactos/dll/directx/wine/d3d9/cubetexture.c +++ b/reactos/dll/directx/wine/d3d9/cubetexture.c @@ -61,10 +61,10 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa if (ref == 0) { TRACE("Releasing child %p\n", This->wineD3DCubeTexture); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D9CB_DestroySurface); IDirect3DDevice9Ex_Release(This->parentDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); HeapFree(GetProcessHeap(), 0, This); } @@ -78,14 +78,15 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_GetDevice(LPDIRECT3DCUBETEXTURE9 HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetDevice(This->wineD3DCubeTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -94,9 +95,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_SetPrivateData(LPDIRECT3DCUBETEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_SetPrivateData(This->wineD3DCubeTexture,refguid,pData,SizeOfData,Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -105,9 +107,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_GetPrivateData(LPDIRECT3DCUBETEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetPrivateData(This->wineD3DCubeTexture,refguid,pData,pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -116,9 +119,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_FreePrivateData(LPDIRECT3DCUBETE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_FreePrivateData(This->wineD3DCubeTexture,refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -127,9 +131,10 @@ static DWORD WINAPI IDirect3DCubeTexture9Impl_SetPriority(LPDIRECT3DCUBETEXTURE9 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_SetPriority(This->wineD3DCubeTexture, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -138,9 +143,10 @@ static DWORD WINAPI IDirect3DCubeTexture9Impl_GetPriority(LPDIRECT3DCUBETEXTURE9 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_GetPriority(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -148,9 +154,9 @@ static void WINAPI IDirect3DCubeTexture9Impl_PreLoad(LPDIRECT3DCUBETEXTURE9 ifac IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DCubeTexture_PreLoad(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DCubeTexture9Impl_GetType(LPDIRECT3DCUBETEXTURE9 iface) { @@ -158,9 +164,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DCubeTexture9Impl_GetType(LPDIRECT3DCUBETE D3DRESOURCETYPE ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_GetType(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -170,9 +177,10 @@ static DWORD WINAPI IDirect3DCubeTexture9Impl_SetLOD(LPDIRECT3DCUBETEXTURE9 ifac DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_SetLOD(This->wineD3DCubeTexture, LODNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -181,9 +189,10 @@ static DWORD WINAPI IDirect3DCubeTexture9Impl_GetLOD(LPDIRECT3DCUBETEXTURE9 ifac DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_GetLOD(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -192,9 +201,10 @@ static DWORD WINAPI IDirect3DCubeTexture9Impl_GetLevelCount(LPDIRECT3DCUBETEXTUR DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DCubeTexture_GetLevelCount(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -203,9 +213,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_SetAutoGenFilterType(LPDIRECT3DC HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_SetAutoGenFilterType(This->wineD3DCubeTexture, (WINED3DTEXTUREFILTERTYPE) FilterType); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -214,9 +225,10 @@ static D3DTEXTUREFILTERTYPE WINAPI IDirect3DCubeTexture9Impl_GetAutoGenFilterTyp D3DTEXTUREFILTERTYPE ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = (D3DTEXTUREFILTERTYPE) IWineD3DCubeTexture_GetAutoGenFilterType(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -224,37 +236,34 @@ static void WINAPI IDirect3DCubeTexture9Impl_GenerateMipSubLevels(LPDIRECT3DCUBE IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DCubeTexture_GenerateMipSubLevels(This->wineD3DCubeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } /* IDirect3DCubeTexture9 Interface follow: */ static HRESULT WINAPI IDirect3DCubeTexture9Impl_GetLevelDesc(LPDIRECT3DCUBETEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *) &pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_GetLevelDesc(This->wineD3DCubeTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -266,13 +275,14 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_GetCubeMapSurface(LPDIRECT3DCUBE TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DCubeTexture_GetCubeMapSurface(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level, &mySurface); if (hrc == D3D_OK && NULL != ppCubeMapSurface) { IWineD3DCubeTexture_GetParent(mySurface, (IUnknown **)ppCubeMapSurface); IWineD3DCubeTexture_Release(mySurface); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -281,9 +291,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_LockRect(LPDIRECT3DCUBETEXTURE9 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_LockRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -292,9 +303,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_UnlockRect(LPDIRECT3DCUBETEXTURE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_UnlockRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, Level); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -303,9 +315,10 @@ static HRESULT WINAPI IDirect3DCubeTexture9Impl_AddDirtyRect(LPDIRECT3DCUBETEXT HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DCubeTexture_AddDirtyRect(This->wineD3DCubeTexture, (WINED3DCUBEMAP_FACES) FaceType, pDirtyRect); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -363,10 +376,11 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9EX ifac } object->lpVtbl = &Direct3DCubeTexture9_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (hr != D3D_OK){ diff --git a/reactos/dll/directx/wine/d3d9/d3d9_main.c b/reactos/dll/directx/wine/d3d9/d3d9_main.c index 40d73a54e7a..f59fc463247 100644 --- a/reactos/dll/directx/wine/d3d9/d3d9_main.c +++ b/reactos/dll/directx/wine/d3d9/d3d9_main.c @@ -25,15 +25,6 @@ #include "initguid.h" #include "d3d9_private.h" -static CRITICAL_SECTION_DEBUG d3d9_cs_debug = -{ - 0, 0, &d3d9_cs, - { &d3d9_cs_debug.ProcessLocksList, - &d3d9_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": d3d9_cs") } -}; -CRITICAL_SECTION d3d9_cs = { &d3d9_cs_debug, -1, 0, 0, 0, 0 }; - WINE_DEFAULT_DEBUG_CHANNEL(d3d9); static int D3DPERF_event_level = 0; @@ -47,9 +38,10 @@ IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) { object->lpVtbl = &Direct3D9_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); object->WineD3D = WineDirect3DCreate(9, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); TRACE("SDKVersion = %x, Created Direct3D object @ %p, WineObj @ %p\n", SDKVersion, object, object->WineD3D); diff --git a/reactos/dll/directx/wine/d3d9/d3d9_private.h b/reactos/dll/directx/wine/d3d9/d3d9_private.h index 7e439749a7b..b6ef7cf90cb 100644 --- a/reactos/dll/directx/wine/d3d9/d3d9_private.h +++ b/reactos/dll/directx/wine/d3d9/d3d9_private.h @@ -3,7 +3,7 @@ * * Copyright 2002-2003 Jason Edmeades * Copyright 2002-2003 Raphael Junqueira - * Copyright 2005 Oliver Stieber + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,7 +44,6 @@ extern HRESULT vdecl_convert_fvf( DWORD FVF, D3DVERTEXELEMENT9** ppVertexElements); -extern CRITICAL_SECTION d3d9_cs; D3DFORMAT d3dformat_from_wined3dformat(WINED3DFORMAT format); WINED3DFORMAT wined3dformat_from_d3dformat(D3DFORMAT format); @@ -369,7 +368,6 @@ typedef struct IDirect3DBaseTexture9Impl /* IDirect3DResource9 fields */ IWineD3DBaseTexture *wineD3DBaseTexture; - } IDirect3DBaseTexture9Impl; /* --------------------- */ diff --git a/reactos/dll/directx/wine/d3d9/device.c b/reactos/dll/directx/wine/d3d9/device.c index e5ca4c4afd0..5a87a8f1ef3 100644 --- a/reactos/dll/directx/wine/d3d9/device.c +++ b/reactos/dll/directx/wine/d3d9/device.c @@ -248,7 +248,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9EX iface) { unsigned i; This->inDestruction = TRUE; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); for(i = 0; i < This->numConvertedDecls; i++) { /* Unless Wine is buggy or the app has a bug the refcount will be 0, because decls hold a reference to the * device @@ -259,7 +259,8 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9EX iface) { IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroyDepthStencilSurface, D3D9CB_DestroySwapChain); IWineD3DDevice_Release(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -271,9 +272,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p)\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + if(hr == WINED3D_OK && This->notreset) { TRACE("D3D9 Device is marked not reset\n"); hr = D3DERR_DEVICENOTRESET; @@ -287,9 +289,10 @@ static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetAvailableTextureMem(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -298,9 +301,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(LPDIRECT3DDEV HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_EvictManagedResources(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -315,7 +319,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9EX iface return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDirect3D(This->WineD3DDevice, &pWineD3D); if (hr == D3D_OK && pWineD3D != NULL) { @@ -326,7 +330,8 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9EX iface *ppD3D9 = NULL; } TRACE("(%p) returning %p\n", This, *ppD3D9); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -345,9 +350,11 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9EX i } memset(pCaps, 0, sizeof(*pCaps)); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pWineCaps); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + WINECAPSTOD3D9CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); @@ -365,9 +372,9 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDisplayMode(This->WineD3DDevice, iSwapChain, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -379,9 +386,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(LPDIRECT3DDEV HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetCreationParameters(This->WineD3DDevice, (WINED3DDEVICE_CREATION_PARAMETERS *) pParameters); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -396,9 +404,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVIC return WINED3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice, XHotSpot, YHotSpot, pSurface->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -406,9 +415,9 @@ static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9 IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetCursorPosition(This->WineD3DDevice, XScreenSpace, YScreenSpace, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9EX iface, BOOL bShow) { @@ -416,53 +425,35 @@ static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9EX ifac BOOL ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DDevice_ShowCursor(This->WineD3DDevice, bShow); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data) { BOOL *resources_ok = data; - WINED3DRESOURCETYPE type; + D3DRESOURCETYPE type; HRESULT ret = S_OK; WINED3DSURFACE_DESC surface_desc; WINED3DVOLUME_DESC volume_desc; D3DINDEXBUFFER_DESC index_desc; D3DVERTEXBUFFER_DESC vertex_desc; - WINED3DFORMAT dummy_format; - WINED3DMULTISAMPLE_TYPE dummy_multisampletype; - DWORD dummy_dword; - WINED3DPOOL pool = WINED3DPOOL_SCRATCH; /* a harmless pool */ + WINED3DPOOL pool; IDirect3DResource9 *parent; IWineD3DResource_GetParent(resource, (IUnknown **) &parent); type = IDirect3DResource9_GetType(parent); switch(type) { case D3DRTYPE_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_multisampletype; - surface_desc.MultiSampleQuality = &dummy_dword; - surface_desc.Width = &dummy_dword; - surface_desc.Height = &dummy_dword; - IWineD3DSurface_GetDesc((IWineD3DSurface *) resource, &surface_desc); + pool = surface_desc.pool; break; case D3DRTYPE_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); + pool = volume_desc.Pool; break; case D3DRTYPE_INDEXBUFFER: @@ -479,6 +470,7 @@ static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data * is a D3DPOOL_DEFAULT surface or volume as well */ default: + pool = WINED3DPOOL_SCRATCH; /* a harmless pool */ break; } @@ -515,7 +507,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9EX iface, D3 * 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 */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetIndices(This->WineD3DDevice, NULL, WINED3DFMT_UNKNOWN); for(i = 0; i < 16; i++) { IWineD3DDevice_SetStreamSource(This->WineD3DDevice, i, NULL, 0, 0); @@ -528,7 +520,8 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9EX iface, D3 if(!resources_ok) { WARN("The application is holding D3DPOOL_DEFAULT resources, rejecting reset\n"); This->notreset = TRUE; - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return WINED3DERR_INVALIDCALL; } @@ -570,7 +563,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9EX iface, D3 This->notreset = FALSE; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -581,9 +574,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9EX iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_Present(This->WineD3DDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -594,13 +588,14 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9EX i TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); 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); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return rc; } static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { @@ -608,9 +603,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetRasterStatus(This->WineD3DDevice, iSwapChain, (WINED3DRASTER_STATUS *) pRasterStatus); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -619,48 +615,49 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetDialogBoxMode(This->WineD3DDevice, bEnableDialogs); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) { - +static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(IDirect3DDevice9Ex *iface, UINT iSwapChain, + DWORD Flags, const D3DGAMMARAMP *pRamp) +{ IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */ + wined3d_mutex_lock(); IWineD3DDevice_SetGammaRamp(This->WineD3DDevice, iSwapChain, Flags, (CONST WINED3DGAMMARAMP *)pRamp); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9EX iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */ + wined3d_mutex_lock(); IWineD3DDevice_GetGammaRamp(This->WineD3DDevice, iSwapChain, (WINED3DGAMMARAMP *) pRamp); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } -static HRESULT 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 ) { +static HRESULT IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, + D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface9 **ppSurface, + UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality) +{ HRESULT hrc; IDirect3DSurface9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p) Relay\n", This); - - if(MultisampleQuality > 0){ + + if (MultisampleQuality > 0) + { FIXME("MultisampleQuality set to %d, bstituting 0\n", MultisampleQuality); - /* - MultisampleQuality - [in] Quality level. The valid range is between zero and one less than the level returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality values of paired render targets, depth stencil surfaces, and the MultiSample type must all match. - */ - - MultisampleQuality=0; + MultisampleQuality = 0; } /*FIXME: Check MAX bounds of MultisampleQuality*/ @@ -676,11 +673,11 @@ static HRESULT IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9EX iface, UIN TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p\n", This, Width, Height, Format, *ppSurface); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, wined3dformat_from_d3dformat(Format), - Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage & WINED3DUSAGE_MASK, - (WINED3DPOOL)Pool, MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + Lockable, Discard, Level, &object->wineD3DSurface, Usage & WINED3DUSAGE_MASK, (WINED3DPOOL)Pool, + MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object); + wined3d_mutex_unlock(); if (hrc != D3D_OK || NULL == object->wineD3DSurface) { @@ -696,17 +693,17 @@ static HRESULT IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9EX iface, UIN return hrc; } - - -static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, - D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, BOOL Lockable, - IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { +static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT Width, UINT Height, + D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, + IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) +{ HRESULT hr; TRACE("Relay\n"); - hr = IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,Lockable,FALSE/*Discard*/, 0/*Level*/, ppSurface,D3DRTYPE_SURFACE,D3DUSAGE_RENDERTARGET,D3DPOOL_DEFAULT,MultiSample,MultisampleQuality,pSharedHandle); - return hr; + hr = IDirect3DDevice9Impl_CreateSurface(iface, Width, Height, Format, Lockable, FALSE /* Discard */, + 0 /* Level */, ppSurface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, MultiSample, MultisampleQuality); + + return hr; } static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE9EX iface, UINT Width, UINT Height, @@ -716,10 +713,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3 HRESULT hr; TRACE("Relay\n"); - hr = IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,TRUE/* Lockable */,Discard, 0/* Level */ - ,ppSurface,D3DRTYPE_SURFACE,D3DUSAGE_DEPTHSTENCIL, - D3DPOOL_DEFAULT,MultiSample,MultisampleQuality,pSharedHandle); - return hr; + hr = IDirect3DDevice9Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, Discard, + 0 /* Level */, ppSurface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, MultiSample, MultisampleQuality); + + return hr; } @@ -728,9 +725,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_UpdateSurface(This->WineD3DDevice, ((IDirect3DSurface9Impl *)pSourceSurface)->wineD3DSurface, pSourceRect, ((IDirect3DSurface9Impl *)pDestinationSurface)->wineD3DSurface, pDestPoint); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -739,9 +737,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_UpdateTexture(This->WineD3DDevice, ((IDirect3DBaseTexture9Impl *)pSourceTexture)->wineD3DBaseTexture, ((IDirect3DBaseTexture9Impl *)pDestinationTexture)->wineD3DBaseTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -752,9 +751,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(LPDIRECT3DDEVIC HRESULT hr; TRACE("(%p)->(%p,%p)\n" , This, renderTarget, destSurface); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_BltFast(destSurface->wineD3DSurface, 0, 0, renderTarget->wineD3DSurface, NULL, WINEDDBLTFAST_NOCOLORKEY); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -764,9 +764,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(LPDIRECT3DDEVICE HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetFrontBufferData(This->WineD3DDevice, iSwapChain, destSurface->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -777,9 +778,11 @@ static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(LPDIRECT3DDEVICE9EX ifa HRESULT hr; TRACE("(%p)->(%p,%p,%p,%p,%d)\n" , This, src, pSourceRect, dst, pDestRect, Filter); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DSurface_Blt(dst->wineD3DSurface, pDestRect, src->wineD3DSurface, pSourceRect, 0, NULL, Filter); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -793,19 +796,18 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9EX iface HRESULT hr; TRACE("(%p) Relay\n" , This); - memset(&desc, 0, sizeof(desc)); - desc.Usage = &usage; - desc.Pool = &pool; - desc.Type = &restype; + wined3d_mutex_lock(); - EnterCriticalSection(&d3d9_cs); IWineD3DSurface_GetDesc(surface->wineD3DSurface, &desc); + usage = desc.usage; + pool = desc.pool; + restype = desc.resource_type; /* 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)) { - LeaveCriticalSection(&d3d9_cs); + if(!(usage & WINED3DUSAGE_RENDERTARGET) && (pool != WINED3DPOOL_DEFAULT || restype != WINED3DRTYPE_SURFACE)) { + wined3d_mutex_unlock(); WARN("Surface is not a render target, or not a stand-alone D3DPOOL_DEFAULT surface\n"); return D3DERR_INVALIDCALL; } @@ -813,7 +815,9 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9EX iface /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */ /* Note: D3DRECT is compatible with WINED3DRECT */ hr = IWineD3DDevice_ColorFill(This->WineD3DDevice, surface->wineD3DSurface, (CONST WINED3DRECT*)pRect, color); - LeaveCriticalSection(&d3d9_cs); + + wined3d_mutex_unlock(); + return hr; } @@ -823,15 +827,17 @@ static HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIREC if(Pool == D3DPOOL_MANAGED ){ FIXME("Attempting to create a managed offscreen plain surface\n"); return D3DERR_INVALIDCALL; - } + } /* '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. Why, their always lockable? - should I change the usage to dynamic? + should I change the usage to dynamic? */ - hr = IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,TRUE/*Loackable*/,FALSE/*Discard*/,0/*Level*/ , ppSurface,D3DRTYPE_SURFACE, 0/*Usage (undefined/none)*/,(WINED3DPOOL) Pool,D3DMULTISAMPLE_NONE,0/*MultisampleQuality*/,pSharedHandle); + hr = IDirect3DDevice9Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, FALSE /* Discard */, + 0 /* Level */, ppSurface, 0 /* Usage (undefined/none) */, (WINED3DPOOL)Pool, D3DMULTISAMPLE_NONE, + 0 /* MultisampleQuality */); return hr; } @@ -843,16 +849,17 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetRenderTarget(This->WineD3DDevice, RenderTargetIndex, pSurface ? pSurface->wineD3DSurface : NULL); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9EX iface, DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hr = D3D_OK; IWineD3DSurface *pRenderTarget; + HRESULT hr; TRACE("(%p) Relay\n" , This); @@ -860,17 +867,25 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9EX return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); + hr=IWineD3DDevice_GetRenderTarget(This->WineD3DDevice,RenderTargetIndex,&pRenderTarget); - if (hr == D3D_OK && pRenderTarget != NULL) { - IWineD3DSurface_GetParent(pRenderTarget,(IUnknown**)ppRenderTarget); - IWineD3DSurface_Release(pRenderTarget); - } else { - FIXME("Call to IWineD3DDevice_GetRenderTarget failed\n"); + if (FAILED(hr)) + { + FIXME("Call to IWineD3DDevice_GetRenderTarget failed, hr %#x\n", hr); + } + else if (!pRenderTarget) + { *ppRenderTarget = NULL; } - LeaveCriticalSection(&d3d9_cs); + else + { + IWineD3DSurface_GetParent(pRenderTarget, (IUnknown **)ppRenderTarget); + IWineD3DSurface_Release(pRenderTarget); + } + + wined3d_mutex_unlock(); return hr; } @@ -882,9 +897,11 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDE TRACE("(%p) Relay\n" , This); pSurface = (IDirect3DSurface9Impl*)pZStencilSurface; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_SetDepthStencilSurface(This->WineD3DDevice, NULL==pSurface ? NULL : pSurface->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -898,7 +915,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDE return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetDepthStencilSurface(This->WineD3DDevice,&pZStencilSurface); if (hr == WINED3D_OK) { IWineD3DSurface_GetParent(pZStencilSurface,(IUnknown**)ppZStencilSurface); @@ -908,7 +925,8 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDE WARN("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr); *ppZStencilSurface = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -917,9 +935,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9EX ifac HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_BeginScene(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -928,9 +947,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9EX iface) HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_EndScene(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -940,9 +960,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9EX iface, DW TRACE("(%p) Relay\n" , This); /* Note: D3DRECT is compatible with WINED3DRECT */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_Clear(This->WineD3DDevice, Count, (CONST WINED3DRECT*) pRects, Flags, Color, Z, Stencil); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -952,9 +973,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9EX if TRACE("(%p) Relay\n" , This); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTransform(This->WineD3DDevice, State, (CONST WINED3DMATRIX*) lpMatrix); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -964,10 +986,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9EX if TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ + wined3d_mutex_lock(); hr = IWineD3DDevice_GetTransform(This->WineD3DDevice, State, (WINED3DMATRIX*) pMatrix); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -978,9 +1000,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9 TRACE("(%p) Relay\n" , This); /* Note: D3DMATRIX is compatible with WINED3DMATRIX */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_MultiplyTransform(This->WineD3DDevice, State, (CONST WINED3DMATRIX*) pMatrix); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -990,9 +1013,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(LPDIRECT3DDEVICE9EX ifa TRACE("(%p) Relay\n" , This); /* Note: D3DVIEWPORT9 is compatible with WINED3DVIEWPORT */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetViewport(This->WineD3DDevice, (const WINED3DVIEWPORT *)pViewport); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1002,9 +1026,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(LPDIRECT3DDEVICE9EX ifa TRACE("(%p) Relay\n" , This); /* Note: D3DVIEWPORT9 is compatible with WINED3DVIEWPORT */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetViewport(This->WineD3DDevice, (WINED3DVIEWPORT *)pViewport); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1014,9 +1039,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(LPDIRECT3DDEVICE9EX ifa TRACE("(%p) Relay\n" , This); /* Note: D3DMATERIAL9 is compatible with WINED3DMATERIAL */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetMaterial(This->WineD3DDevice, (const WINED3DMATERIAL *)pMaterial); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1026,9 +1052,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(LPDIRECT3DDEVICE9EX ifa TRACE("(%p) Relay\n" , This); /* Note: D3DMATERIAL9 is compatible with WINED3DMATERIAL */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetMaterial(This->WineD3DDevice, (WINED3DMATERIAL *)pMaterial); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1038,9 +1065,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(LPDIRECT3DDEVICE9EX iface, TRACE("(%p) Relay\n" , This); /* Note: D3DLIGHT9 is compatible with WINED3DLIGHT */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetLight(This->WineD3DDevice, Index, (const WINED3DLIGHT *)pLight); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1050,9 +1078,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(LPDIRECT3DDEVICE9EX iface, TRACE("(%p) Relay\n" , This); /* Note: D3DLIGHT9 is compatible with WINED3DLIGHT */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetLight(This->WineD3DDevice, Index, (WINED3DLIGHT *)pLight); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1061,9 +1090,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(LPDIRECT3DDEVICE9EX ifa HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetLightEnable(This->WineD3DDevice, Index, Enable); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1072,9 +1102,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetLightEnable(This->WineD3DDevice, Index, pEnable); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1083,9 +1114,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(LPDIRECT3DDEVICE9EX if HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetClipPlane(This->WineD3DDevice, Index, pPlane); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1094,9 +1126,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(LPDIRECT3DDEVICE9EX if HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetClipPlane(This->WineD3DDevice, Index, pPlane); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1105,9 +1138,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetRenderState(This->WineD3DDevice, State, Value); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1116,9 +1150,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetRenderState(This->WineD3DDevice, State, pValue); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1127,9 +1162,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetClipStatus(This->WineD3DDevice, (const WINED3DCLIPSTATUS *)pClipStatus); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1138,9 +1174,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetClipStatus(This->WineD3DDevice, (WINED3DCLIPSTATUS *)pClipStatus); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1155,7 +1192,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9EX ifac return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, &retTexture); if (SUCCEEDED(rc) && NULL != retTexture) { IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); @@ -1166,7 +1203,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9EX ifac } *ppTexture = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return rc; } @@ -1176,10 +1213,11 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9EX ifac HRESULT hr; TRACE("(%p) Relay %d %p\n" , This, Stage, pTexture); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTexture(This->WineD3DDevice, Stage, pTexture==NULL ? NULL:((IDirect3DBaseTexture9Impl *)pTexture)->wineD3DBaseTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1225,9 +1263,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, tss_lookup[Type], pValue); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1236,20 +1275,24 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVI HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, tss_lookup[Type], Value); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9EX iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(IDirect3DDevice9Ex *iface, DWORD Sampler, + D3DSAMPLERSTATETYPE Type, DWORD *pValue) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Sampler, Type, pValue); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1258,9 +1301,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetSamplerState(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Sampler, Type, Value); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1269,20 +1313,24 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_ValidateDevice(This->WineD3DDevice, pNumPasses); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(LPDIRECT3DDEVICE9EX iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(IDirect3DDevice9Ex *iface, UINT PaletteNumber, + const PALETTEENTRY *pEntries) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1291,9 +1339,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(LPDIRECT3DDEVICE9 HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1302,9 +1351,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(LPDIRECT3D HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1313,9 +1363,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(LPDIRECT3D HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1324,9 +1375,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetScissorRect(This->WineD3DDevice, pRect); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1335,9 +1387,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetScissorRect(This->WineD3DDevice, pRect); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1346,9 +1399,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIREC HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetSoftwareVertexProcessing(This->WineD3DDevice, bSoftware); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1357,9 +1411,10 @@ static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(LPDIREC BOOL ret; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -1368,9 +1423,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetNPatchMode(This->WineD3DDevice, nSegments); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1379,22 +1435,26 @@ static float WINAPI IDirect3DDevice9Impl_GetNPatchMode(LPDIRECT3DDEVICE9EX i float ret; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DDevice_GetNPatchMode(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, UINT PrimitiveCount) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawPrimitive(This->WineD3DDevice, StartVertex, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount)); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1405,26 +1465,30 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(LPDIRECT3DDEVI TRACE("(%p) Relay\n" , This); /* D3D8 passes the baseVertexIndex in SetIndices, and due to the stateblock functions wined3d has to work that way */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetBaseVertexIndex(This->WineD3DDevice, BaseVertexIndex); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawIndexedPrimitive(This->WineD3DDevice, MinVertexIndex, NumVertices, startIndex, vertex_count_from_primitive_count(PrimitiveType, primCount)); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE9EX iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawPrimitiveUP(This->WineD3DDevice, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pVertexStreamZeroData, VertexStreamZeroStride); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1435,12 +1499,13 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDE HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPrimitiveType(This->WineD3DDevice, PrimitiveType); hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->WineD3DDevice, MinVertexIndex, NumVertexIndices, vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pIndexData, wined3dformat_from_d3dformat(IndexDataFormat), pVertexStreamZeroData, VertexStreamZeroStride); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1451,9 +1516,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9EX IDirect3DVertexBuffer9Impl *dest = (IDirect3DVertexBuffer9Impl *) pDestBuffer; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_ProcessVertices(This->WineD3DDevice,SrcStartIndex, DestIndex, VertexCount, dest->wineD3DVertexBuffer, Decl ? Decl->wineD3DVertexDeclaration : NULL, Flags, dest->fvf); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1527,9 +1593,9 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9EX iface, DWO return D3D_OK; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); decl = getConvertedDecl(This, FVF); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (!decl) { @@ -1578,11 +1644,12 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetStreamSource(This->WineD3DDevice, StreamNumber, - pStreamData==NULL ? NULL:((IDirect3DVertexBuffer9Impl *)pStreamData)->wineD3DVertexBuffer, - OffsetInBytes, Stride); - LeaveCriticalSection(&d3d9_cs); + pStreamData ? ((IDirect3DVertexBuffer9Impl *)pStreamData)->wineD3DVertexBuffer : NULL, + OffsetInBytes, Stride); + wined3d_mutex_unlock(); + return hr; } @@ -1597,7 +1664,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9EX i return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, &retStream, OffsetInBytes, pStride); if (rc == D3D_OK && NULL != retStream) { IWineD3DBuffer_GetParent(retStream, (IUnknown **)pStream); @@ -1608,19 +1675,22 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9EX i } *pStream = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return rc; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(LPDIRECT3DDEVICE9EX iface, UINT StreamNumber, UINT Divider) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT StreamNumber, + UINT Divider) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetStreamSourceFreq(This->WineD3DDevice, StreamNumber, Divider); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1629,9 +1699,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(LPDIRECT3DDEVIC HRESULT hr; TRACE("(%p) Relay\n" , This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetStreamSourceFreq(This->WineD3DDevice, StreamNumber, Divider); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1641,11 +1712,12 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(LPDIRECT3DDEVICE9EX ifac IDirect3DIndexBuffer9Impl *ib = (IDirect3DIndexBuffer9Impl *) pIndexData; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetIndices(This->WineD3DDevice, ib ? ib->wineD3DIndexBuffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1660,7 +1732,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9EX ifac return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); rc = IWineD3DDevice_GetIndices(This->WineD3DDevice, &retIndexData); if (SUCCEEDED(rc) && retIndexData) { IWineD3DBuffer_GetParent(retIndexData, (IUnknown **)ppIndexData); @@ -1669,7 +1741,8 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9EX ifac if (FAILED(rc)) FIXME("Call to GetIndices failed\n"); *ppIndexData = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return rc; } @@ -1678,9 +1751,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9EX i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DrawRectPatch(This->WineD3DDevice, Handle, pNumSegs, (CONST WINED3DRECTPATCH_INFO *)pRectPatchInfo); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1689,9 +1763,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9EX if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DrawTriPatch(This->WineD3DDevice, Handle, pNumSegs, (CONST WINED3DTRIPATCH_INFO *)pTriPatchInfo); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1700,9 +1775,10 @@ static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(LPDIRECT3DDEVICE9EX ifa HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_DeletePatch(This->WineD3DDevice, Handle); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -1995,12 +2071,12 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen "\tpool %#x, level %u, face %u, surface %p\n", iface, superior, width, height, format, usage, pool, level, face, surface); - if (pool == D3DPOOL_DEFAULT && !(usage & D3DUSAGE_DYNAMIC)) lockable = FALSE; + if (pool == WINED3DPOOL_DEFAULT && !(usage & D3DUSAGE_DYNAMIC)) + lockable = FALSE; hr = IDirect3DDevice9Impl_CreateSurface((IDirect3DDevice9Ex *)This, width, height, d3dformat_from_wined3dformat(format), lockable, FALSE /* Discard */, level, - (IDirect3DSurface9 **)&d3d_surface, D3DRTYPE_SURFACE, usage, pool, - D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */, NULL); + (IDirect3DSurface9 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */); if (FAILED(hr)) { ERR("(%p) CreateSurface failed, returning %#x\n", iface, hr); diff --git a/reactos/dll/directx/wine/d3d9/directx.c b/reactos/dll/directx/wine/d3d9/directx.c index e9547a764e4..fe229166904 100644 --- a/reactos/dll/directx/wine/d3d9/directx.c +++ b/reactos/dll/directx/wine/d3d9/directx.c @@ -69,9 +69,10 @@ static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9EX iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3D_Release(This->WineD3D); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } @@ -84,9 +85,10 @@ static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9EX ifac HRESULT hr; TRACE("(%p)->(%p)\n", This, pInitializeFunction); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_RegisterSoftwareDevice(This->WineD3D, pInitializeFunction); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -95,9 +97,10 @@ static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9EX iface) { HRESULT hr; TRACE("%p\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterCount(This->WineD3D); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -106,23 +109,25 @@ static HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9EX iface, U WINED3DADAPTER_IDENTIFIER adapter_id; HRESULT hr; - /* dx8 and dx9 have different structures to be filled in, with incompatible - layouts so pass in pointers to the places to be filled via an internal - structure */ - adapter_id.Driver = pIdentifier->Driver; - adapter_id.Description = pIdentifier->Description; - adapter_id.DeviceName = pIdentifier->DeviceName; - adapter_id.DriverVersion = &pIdentifier->DriverVersion; - adapter_id.VendorId = &pIdentifier->VendorId; - adapter_id.DeviceId = &pIdentifier->DeviceId; - adapter_id.SubSysId = &pIdentifier->SubSysId; - adapter_id.Revision = &pIdentifier->Revision; - adapter_id.DeviceIdentifier = &pIdentifier->DeviceIdentifier; - adapter_id.WHQLLevel = &pIdentifier->WHQLLevel; + adapter_id.driver = pIdentifier->Driver; + adapter_id.driver_size = sizeof(pIdentifier->Driver); + adapter_id.description = pIdentifier->Description; + adapter_id.description_size = sizeof(pIdentifier->Description); + adapter_id.device_name = pIdentifier->DeviceName; + adapter_id.device_name_size = sizeof(pIdentifier->DeviceName); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterIdentifier(This->WineD3D, Adapter, Flags, &adapter_id); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + + pIdentifier->DriverVersion = adapter_id.driver_version; + pIdentifier->VendorId = adapter_id.vendor_id; + pIdentifier->DeviceId = adapter_id.device_id; + pIdentifier->SubSysId = adapter_id.subsystem_id; + pIdentifier->Revision = adapter_id.revision; + memcpy(&pIdentifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(pIdentifier->DeviceIdentifier)); + pIdentifier->WHQLLevel = adapter_id.whql_level; + return hr; } @@ -136,9 +141,10 @@ static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9EX iface, UINT return 0; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterModeCount(This->WineD3D, Adapter, wined3dformat_from_d3dformat(Format)); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -151,10 +157,10 @@ static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9EX iface, UINT if(Format != D3DFMT_X8R8G8B8 && Format != D3DFMT_R5G6B5) return D3DERR_INVALIDCALL; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, wined3dformat_from_d3dformat(Format), Mode, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -165,38 +171,51 @@ static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9EX iface, IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9EX iface, - UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat, - D3DFORMAT BackBufferFormat, BOOL Windowed) { +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(IDirect3D9Ex *iface, UINT Adapter, + D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) +{ IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("(%p)->(%d, %d, %d, %d, %s\n", This, Adapter, CheckType, DisplayFormat, BackBufferFormat, Windowed ? "true" : "false"); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceType(This->WineD3D, Adapter, CheckType, wined3dformat_from_d3dformat(DisplayFormat), wined3dformat_from_d3dformat(BackBufferFormat), Windowed); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9EX iface, - UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, - DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(IDirect3D9Ex *iface, UINT Adapter, D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) +{ IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; WINED3DRESOURCETYPE WineD3DRType; TRACE("%p\n", This); + /* 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 + * support this format uncovers a bug in Battlefield 1942 (fonts are missing) + * So do the same as Windows drivers and pretend not to support it on dx8 and 9 + */ + if(CheckFormat == D3DFMT_R8G8B8) + { + WARN("D3DFMT_R8G8B8 is not available on windows, returning D3DERR_NOTAVAILABLE\n"); + return D3DERR_NOTAVAILABLE; + } + switch(RType) { case D3DRTYPE_VERTEXBUFFER: case D3DRTYPE_INDEXBUFFER: @@ -208,39 +227,43 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9EX iface, break; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(AdapterFormat), Usage, WineD3DRType, wined3dformat_from_d3dformat(CheckFormat), SURFACE_OPENGL); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9EX iface, - UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, - BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { +static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(IDirect3D9Ex *iface, UINT Adapter, + D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD *pQualityLevels) +{ IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("%p\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceMultiSampleType(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(SurfaceFormat), Windowed, MultiSampleType, pQualityLevels); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9EX iface, - UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, - D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { +static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(IDirect3D9Ex *iface, UINT Adapter, + D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) +{ IDirect3D9Impl *This = (IDirect3D9Impl *)iface; HRESULT hr; TRACE("%p\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDepthStencilMatch(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(AdapterFormat), wined3dformat_from_d3dformat(RenderTargetFormat), wined3dformat_from_d3dformat(DepthStencilFormat)); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -249,10 +272,11 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9EX i HRESULT hr; TRACE("%p\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CheckDeviceFormatConversion(This->WineD3D, Adapter, DeviceType, wined3dformat_from_d3dformat(SourceFormat), wined3dformat_from_d3dformat(TargetFormat)); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -330,9 +354,11 @@ static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9EX iface, UINT Ada return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/ } memset(pCaps, 0, sizeof(*pCaps)); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, pWineCaps); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + WINECAPSTOD3D9CAPS(pCaps, pWineCaps) HeapFree(GetProcessHeap(), 0, pWineCaps); @@ -350,9 +376,10 @@ static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9EX iface, UIN HMONITOR ret; TRACE("%p\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3D_GetAdapterMonitor(This->WineD3D, Adapter); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -418,13 +445,14 @@ static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9EX iface, UINT Adap *ppReturnedDeviceInterface = (IDirect3DDevice9 *)object; /* Allocate an associated WineD3DDevice object */ - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, (IUnknown *)object, (IWineD3DDeviceParent *)&object->device_parent_vtbl, &object->WineD3DDevice); if (hr != D3D_OK) { HeapFree(GetProcessHeap(), 0, object); *ppReturnedDeviceInterface = NULL; - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -492,7 +520,7 @@ static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9EX iface, UINT Adap * can be used without further checking */ object->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } diff --git a/reactos/dll/directx/wine/d3d9/indexbuffer.c b/reactos/dll/directx/wine/d3d9/indexbuffer.c index 8802bd19780..49f6fc8013a 100644 --- a/reactos/dll/directx/wine/d3d9/indexbuffer.c +++ b/reactos/dll/directx/wine/d3d9/indexbuffer.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DIndexBuffer9Impl_Release(LPDIRECT3DINDEXBUFFER9 ifa TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DBuffer_Release(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -73,14 +74,15 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_GetDevice(LPDIRECT3DINDEXBUFFER9 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDevice(This->wineD3DIndexBuffer, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -89,9 +91,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_SetPrivateData(LPDIRECT3DINDEXBU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_SetPrivateData(This->wineD3DIndexBuffer, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -100,9 +103,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_GetPrivateData(LPDIRECT3DINDEXBU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetPrivateData(This->wineD3DIndexBuffer, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -111,9 +115,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_FreePrivateData(LPDIRECT3DINDEXB HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_FreePrivateData(This->wineD3DIndexBuffer, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -122,9 +127,10 @@ static DWORD WINAPI IDirect3DIndexBuffer9Impl_SetPriority(LPDIRECT3DINDEXBUFFER9 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_SetPriority(This->wineD3DIndexBuffer, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -133,9 +139,10 @@ static DWORD WINAPI IDirect3DIndexBuffer9Impl_GetPriority(LPDIRECT3DINDEXBUFFER9 DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DBuffer_GetPriority(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -143,9 +150,9 @@ static void WINAPI IDirect3DIndexBuffer9Impl_PreLoad(LPDIRECT3DINDEXBUFFER9 ifac IDirect3DIndexBuffer9Impl *This = (IDirect3DIndexBuffer9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DBuffer_PreLoad(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DIndexBuffer9Impl_GetType(LPDIRECT3DINDEXBUFFER9 iface) { @@ -161,9 +168,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_Lock(LPDIRECT3DINDEXBUFFER9 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Map(This->wineD3DIndexBuffer, OffsetToLock, SizeToLock, (BYTE **)ppbData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -172,9 +180,10 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_Unlock(LPDIRECT3DINDEXBUFFER9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Unmap(This->wineD3DIndexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -184,9 +193,9 @@ static HRESULT WINAPI IDirect3DIndexBuffer9Impl_GetDesc(LPDIRECT3DINDEXB WINED3DBUFFER_DESC desc; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDesc(This->wineD3DIndexBuffer, &desc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) { pDesc->Format = d3dformat_from_wined3dformat(This->format); @@ -223,14 +232,13 @@ static const IDirect3DIndexBuffer9Vtbl Direct3DIndexBuffer9_Vtbl = /* IDirect3DDevice9 IDirect3DIndexBuffer9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9EX iface, - UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, - IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) { - +HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT Length, DWORD Usage, + D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9 **ppIndexBuffer, HANDLE *pSharedHandle) +{ IDirect3DIndexBuffer9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; - + TRACE("(%p) Relay\n", This); /* Allocate the storage for the device */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); @@ -243,10 +251,12 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9EX iface, object->ref = 1; object->format = wined3dformat_from_d3dformat(Format); TRACE("Calling wined3d create index buffer\n"); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage & WINED3DUSAGE_MASK, (WINED3DPOOL)Pool, &object->wineD3DIndexBuffer, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + if (hrc != D3D_OK) { /* free up object */ diff --git a/reactos/dll/directx/wine/d3d9/pixelshader.c b/reactos/dll/directx/wine/d3d9/pixelshader.c index 3939f5977a8..37950454521 100644 --- a/reactos/dll/directx/wine/d3d9/pixelshader.c +++ b/reactos/dll/directx/wine/d3d9/pixelshader.c @@ -56,9 +56,10 @@ static ULONG WINAPI IDirect3DPixelShader9Impl_Release(LPDIRECT3DPIXELSHADER9 ifa TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DPixelShader_Release(This->wineD3DPixelShader); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -72,11 +73,12 @@ static HRESULT WINAPI IDirect3DPixelShader9Impl_GetDevice(LPDIRECT3DPIXELSHADER9 TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DPixelShader_GetDevice(This->wineD3DPixelShader, &myDevice); IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); IWineD3DDevice_Release(myDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + TRACE("(%p) returning (%p)\n", This, *ppDevice); return D3D_OK; } @@ -86,9 +88,10 @@ static HRESULT WINAPI IDirect3DPixelShader9Impl_GetFunction(LPDIRECT3DPIXELSHADE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DPixelShader_GetFunction(This->wineD3DPixelShader, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -127,12 +130,14 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9EX iface, object->ref = 1; object->lpVtbl = &Direct3DPixelShader9_Vtbl; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, NULL, &object->wineD3DPixelShader, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); - if (hrc != D3D_OK) { + wined3d_mutex_unlock(); + if (hrc != D3D_OK) + { /* free up object */ FIXME("(%p) call to IWineD3DDevice_CreatePixelShader failed\n", This); HeapFree(GetProcessHeap(), 0 , object); @@ -152,9 +157,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9EX iface, ID IDirect3DPixelShader9Impl *shader = (IDirect3DPixelShader9Impl *)pShader; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DDevice_SetPixelShader(This->WineD3DDevice, shader == NULL ? NULL :shader->wineD3DPixelShader); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return D3D_OK; } @@ -169,7 +175,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9EX iface, ID return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetPixelShader(This->WineD3DDevice, &object); if (SUCCEEDED(hrc)) { @@ -187,7 +193,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9EX iface, ID { WARN("(%p) : Call to IWineD3DDevice_GetPixelShader failed %u (device %p)\n", This, hrc, This->WineD3DDevice); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); TRACE("(%p) : returning %p\n", This, *ppShader); return hrc; @@ -196,11 +202,12 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9EX iface, ID HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9EX iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; - TRACE("(%p) Relay\n", This); + TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -210,9 +217,9 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9EX TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -222,9 +229,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPixelShaderConstantI(This->WineD3DDevice, Register, pConstantData, Vector4iCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -233,9 +241,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPixelShaderConstantI(This->WineD3DDevice, Register, pConstantData, Vector4iCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -244,9 +253,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetPixelShaderConstantB(This->WineD3DDevice, Register, pConstantData, BoolCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -255,8 +265,9 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetPixelShaderConstantB(This->WineD3DDevice, Register, pConstantData, BoolCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d9/query.c b/reactos/dll/directx/wine/d3d9/query.c index 6e4b20a41eb..a17d2e8402a 100644 --- a/reactos/dll/directx/wine/d3d9/query.c +++ b/reactos/dll/directx/wine/d3d9/query.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DQuery9Impl_Release(LPDIRECT3DQUERY9 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DQuery_Release(This->wineD3DQuery); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -74,7 +75,7 @@ static HRESULT WINAPI IDirect3DQuery9Impl_GetDevice(LPDIRECT3DQUERY9 iface, IDir TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DQuery_GetDevice(This->wineD3DQuery, &pDevice); if(hr != D3D_OK){ *ppDevice = NULL; @@ -82,7 +83,8 @@ static HRESULT WINAPI IDirect3DQuery9Impl_GetDevice(LPDIRECT3DQUERY9 iface, IDir hr = IWineD3DDevice_GetParent(pDevice, (IUnknown **)ppDevice); IWineD3DDevice_Release(pDevice); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -91,9 +93,10 @@ static D3DQUERYTYPE WINAPI IDirect3DQuery9Impl_GetType(LPDIRECT3DQUERY9 iface) { HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DQuery_GetType(This->wineD3DQuery); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -102,9 +105,10 @@ static DWORD WINAPI IDirect3DQuery9Impl_GetDataSize(LPDIRECT3DQUERY9 iface) { DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DQuery_GetDataSize(This->wineD3DQuery); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -113,9 +117,10 @@ static HRESULT WINAPI IDirect3DQuery9Impl_Issue(LPDIRECT3DQUERY9 iface, DWORD dw HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DQuery_Issue(This->wineD3DQuery, dwIssueFlags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -124,9 +129,10 @@ static HRESULT WINAPI IDirect3DQuery9Impl_GetData(LPDIRECT3DQUERY9 iface, void* HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DQuery_GetData(This->wineD3DQuery, pData, dwSize, dwGetDataFlags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -154,9 +160,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9EX iface, D3DQU if (!ppQuery) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateQuery(This->WineD3DDevice, Type, NULL, NULL); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -169,9 +176,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9EX iface, D3DQU object->lpVtbl = &Direct3DQuery9_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateQuery(This->WineD3DDevice, Type, &object->wineD3DQuery, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/reactos/dll/directx/wine/d3d9/stateblock.c b/reactos/dll/directx/wine/d3d9/stateblock.c index d17233f124f..29ff5b34d19 100644 --- a/reactos/dll/directx/wine/d3d9/stateblock.c +++ b/reactos/dll/directx/wine/d3d9/stateblock.c @@ -57,9 +57,10 @@ static ULONG WINAPI IDirect3DStateBlock9Impl_Release(LPDIRECT3DSTATEBLOCK9 iface TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DStateBlock_Release(This->wineD3DStateBlock); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -73,25 +74,27 @@ static HRESULT WINAPI IDirect3DStateBlock9Impl_GetDevice(LPDIRECT3DSTATEBLOCK9 i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DStateBlock_GetDevice(This->wineD3DStateBlock, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } static HRESULT WINAPI IDirect3DStateBlock9Impl_Capture(LPDIRECT3DSTATEBLOCK9 iface) { IDirect3DStateBlock9Impl *This = (IDirect3DStateBlock9Impl *)iface; HRESULT hr; - TRACE("(%p) Relay\n", This); + TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DStateBlock_Capture(This->wineD3DStateBlock); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -100,9 +103,10 @@ static HRESULT WINAPI IDirect3DStateBlock9Impl_Apply(LPDIRECT3DSTATEBLOCK9 iface HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DStateBlock_Apply(This->wineD3DStateBlock); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -125,7 +129,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9EX iface, IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DStateBlock9Impl* object; HRESULT hrc = D3D_OK; - + TRACE("(%p) Relay\n", This); if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE && @@ -133,15 +137,16 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9EX iface, WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n"); return D3DERR_INVALIDCALL; } - + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DStateBlock9Impl)); if (NULL == object) return E_OUTOFMEMORY; object->lpVtbl = &Direct3DStateBlock9_Vtbl; object->ref = 1; - - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateStateBlock(This->WineD3DDevice, (WINED3DSTATEBLOCKTYPE)Type, &object->wineD3DStateBlock, (IUnknown*)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + if(hrc != D3D_OK){ FIXME("(%p) Call to IWineD3DDevice_CreateStateBlock failed.\n", This); HeapFree(GetProcessHeap(), 0, object); @@ -155,37 +160,41 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(LPDIRECT3DDEVICE9EX iface, return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(LPDIRECT3DDEVICE9EX iface) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(IDirect3DDevice9Ex *iface) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_BeginStateBlock(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } -HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(LPDIRECT3DDEVICE9EX iface, IDirect3DStateBlock9** ppSB) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **ppSB) +{ + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IWineD3DStateBlock *wineD3DStateBlock; + IDirect3DStateBlock9Impl *object; HRESULT hr; - IWineD3DStateBlock* wineD3DStateBlock; - IDirect3DStateBlock9Impl* object; - TRACE("(%p) Relay\n", This); - + TRACE("(%p) Relay\n", This); + /* Tell wineD3D to endstateblock before anything else (in case we run out - * of memory later and cause locking problems) - */ - EnterCriticalSection(&d3d9_cs); + * of memory later and cause locking problems) */ + wined3d_mutex_lock(); hr=IWineD3DDevice_EndStateBlock(This->WineD3DDevice,&wineD3DStateBlock); - LeaveCriticalSection(&d3d9_cs); - if(hr!= D3D_OK){ + wined3d_mutex_unlock(); + + if (hr!= D3D_OK) + { WARN("IWineD3DDevice_EndStateBlock returned an error\n"); return hr; - } + } /* allocate a new IDirectD3DStateBlock */ - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY ,sizeof(IDirect3DStateBlock9Impl)); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DStateBlock9Impl)); if (!object) return E_OUTOFMEMORY; object->ref = 1; object->lpVtbl = &Direct3DStateBlock9_Vtbl; diff --git a/reactos/dll/directx/wine/d3d9/surface.c b/reactos/dll/directx/wine/d3d9/surface.c index f95c387d560..b4defaf6ee0 100644 --- a/reactos/dll/directx/wine/d3d9/surface.c +++ b/reactos/dll/directx/wine/d3d9/surface.c @@ -78,9 +78,10 @@ static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) { if (ref == 0) { if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice); if (!This->isImplicit) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DSurface_Release(This->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } } @@ -96,14 +97,15 @@ static HRESULT WINAPI IDirect3DSurface9Impl_GetDevice(LPDIRECT3DSURFACE9 iface, HRESULT hr; TRACE("(%p)->(%p)\n", This, ppDevice); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetDevice(This->wineD3DSurface, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -112,9 +114,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_SetPrivateData(LPDIRECT3DSURFACE9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_SetPrivateData(This->wineD3DSurface, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -123,9 +126,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_GetPrivateData(LPDIRECT3DSURFACE9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetPrivateData(This->wineD3DSurface, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -134,9 +138,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_FreePrivateData(LPDIRECT3DSURFACE9 i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_FreePrivateData(This->wineD3DSurface, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -145,9 +150,10 @@ static DWORD WINAPI IDirect3DSurface9Impl_SetPriority(LPDIRECT3DSURFACE9 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_SetPriority(This->wineD3DSurface, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -156,9 +162,10 @@ static DWORD WINAPI IDirect3DSurface9Impl_GetPriority(LPDIRECT3DSURFACE9 iface) HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetPriority(This->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -166,10 +173,9 @@ static void WINAPI IDirect3DSurface9Impl_PreLoad(LPDIRECT3DSURFACE9 iface) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DSurface_PreLoad(This->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); - return ; + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DSurface9Impl_GetType(LPDIRECT3DSURFACE9 iface) { @@ -177,9 +183,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DSurface9Impl_GetType(LPDIRECT3DSURFACE9 i D3DRESOURCETYPE ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DSurface_GetType(This->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -205,28 +212,25 @@ static HRESULT WINAPI IDirect3DSurface9Impl_GetContainer(LPDIRECT3DSURFACE9 ifac static HRESULT WINAPI IDirect3DSurface9Impl_GetDesc(LPDIRECT3DSURFACE9 iface, D3DSURFACE_DESC* pDesc) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetDesc(This->wineD3DSurface, &wined3ddesc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -236,10 +240,11 @@ static HRESULT WINAPI IDirect3DSurface9Impl_LockRect(LPDIRECT3DSURFACE9 iface, D HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); TRACE("(%p) calling IWineD3DSurface_LockRect %p %p %p %d\n", This, This->wineD3DSurface, pLockedRect, pRect, Flags); hr = IWineD3DSurface_LockRect(This->wineD3DSurface, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -248,9 +253,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_UnlockRect(LPDIRECT3DSURFACE9 iface) HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_UnlockRect(This->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + switch(hr) { case WINEDDERR_NOTLOCKED: return D3DERR_INVALIDCALL; @@ -263,9 +269,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_GetDC(LPDIRECT3DSURFACE9 iface, HDC* HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_GetDC(This->wineD3DSurface, phdc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -274,9 +281,10 @@ static HRESULT WINAPI IDirect3DSurface9Impl_ReleaseDC(LPDIRECT3DSURFACE9 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSurface_ReleaseDC(This->wineD3DSurface, hdc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + switch(hr) { case WINEDDERR_NODC: return WINED3DERR_INVALIDCALL; default: return hr; diff --git a/reactos/dll/directx/wine/d3d9/swapchain.c b/reactos/dll/directx/wine/d3d9/swapchain.c index 4f639b17087..fb6680742f2 100644 --- a/reactos/dll/directx/wine/d3d9/swapchain.c +++ b/reactos/dll/directx/wine/d3d9/swapchain.c @@ -62,9 +62,10 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface) if (ref == 0) { if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice); if (!This->isImplicit) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } } @@ -78,9 +79,9 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_Present(LPDIRECT3DSWAPCHAIN9 iface TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_Present(This->wineD3DSwapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -90,9 +91,10 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetFrontBufferData(LPDIRECT3DSWAPC HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_GetFrontBufferData(This->wineD3DSwapChain, ((IDirect3DSurface9Impl *)pDestSurface)->wineD3DSurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -103,13 +105,14 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetBackBuffer(LPDIRECT3DSWAPCHAIN9 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DSwapChain_GetBackBuffer(This->wineD3DSwapChain, iBackBuffer, (WINED3DBACKBUFFER_TYPE) Type, &mySurface); if (hrc == D3D_OK && NULL != mySurface) { IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppBackBuffer); IWineD3DSurface_Release(mySurface); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + /* Do not touch the **ppBackBuffer pointer otherwise! (see device test) */ return hrc; } @@ -119,9 +122,10 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetRasterStatus(LPDIRECT3DSWAPCHAI HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_GetRasterStatus(This->wineD3DSwapChain, (WINED3DRASTER_STATUS *) pRasterStatus); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -130,9 +134,9 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetDisplayMode(LPDIRECT3DSWAPCHAIN HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_GetDisplayMode(This->wineD3DSwapChain, (WINED3DDISPLAYMODE *) pMode); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format); @@ -146,13 +150,14 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetDevice(LPDIRECT3DSWAPCHAIN9 ifa TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DSwapChain_GetDevice(This->wineD3DSwapChain, &device); if (hrc == D3D_OK && NULL != device) { IWineD3DDevice_GetParent(device, (IUnknown **)ppDevice); IWineD3DDevice_Release(device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -163,9 +168,9 @@ static HRESULT WINAPI IDirect3DSwapChain9Impl_GetPresentParameters(LPDIRECT3DSWA TRACE("(%p)->(%p): Relay\n", This, pPresentationParameters); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DSwapChain_GetPresentParameters(This->wineD3DSwapChain, &winePresentParameters); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); pPresentationParameters->BackBufferWidth = winePresentParameters.BackBufferWidth; pPresentationParameters->BackBufferHeight = winePresentParameters.BackBufferHeight; @@ -240,10 +245,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE localParameters.PresentationInterval = pPresentationParameters->PresentationInterval; localParameters.AutoRestoreDisplayMode = TRUE; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, SURFACE_OPENGL); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; @@ -280,7 +285,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9EX iface, UI TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetSwapChain(This->WineD3DDevice, iSwapChain, &swapchain); if (hrc == D3D_OK && NULL != swapchain) { IWineD3DSwapChain_GetParent(swapchain, (IUnknown **)pSwapChain); @@ -288,7 +293,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9EX iface, UI } else { *pSwapChain = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -297,8 +303,9 @@ UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9EX UINT ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DDevice_GetNumberOfSwapChains(This->WineD3DDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } diff --git a/reactos/dll/directx/wine/d3d9/texture.c b/reactos/dll/directx/wine/d3d9/texture.c index f0a9c38ad7e..7db70373833 100644 --- a/reactos/dll/directx/wine/d3d9/texture.c +++ b/reactos/dll/directx/wine/d3d9/texture.c @@ -59,9 +59,10 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DTexture_Destroy(This->wineD3DTexture, D3D9CB_DestroySurface); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -75,14 +76,15 @@ static HRESULT WINAPI IDirect3DTexture9Impl_GetDevice(LPDIRECT3DTEXTURE9 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_GetDevice(This->wineD3DTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -91,9 +93,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_SetPrivateData(LPDIRECT3DTEXTURE9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_SetPrivateData(This->wineD3DTexture, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -102,9 +105,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_GetPrivateData(LPDIRECT3DTEXTURE9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_GetPrivateData(This->wineD3DTexture, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -113,9 +117,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_FreePrivateData(LPDIRECT3DTEXTURE9 i HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_FreePrivateData(This->wineD3DTexture, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -124,9 +129,10 @@ static DWORD WINAPI IDirect3DTexture9Impl_SetPriority(LPDIRECT3DTEXTURE9 iface, DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_SetPriority(This->wineD3DTexture, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -135,9 +141,10 @@ static DWORD WINAPI IDirect3DTexture9Impl_GetPriority(LPDIRECT3DTEXTURE9 iface) DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetPriority(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -145,9 +152,9 @@ static void WINAPI IDirect3DTexture9Impl_PreLoad(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DTexture_PreLoad(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DTexture9Impl_GetType(LPDIRECT3DTEXTURE9 iface) { @@ -155,9 +162,10 @@ static D3DRESOURCETYPE WINAPI IDirect3DTexture9Impl_GetType(LPDIRECT3DTEXTURE9 i HRESULT ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetType(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -167,9 +175,10 @@ static DWORD WINAPI IDirect3DTexture9Impl_SetLOD(LPDIRECT3DTEXTURE9 iface, DWORD DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_SetLOD(This->wineD3DTexture, LODNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -178,9 +187,10 @@ static DWORD WINAPI IDirect3DTexture9Impl_GetLOD(LPDIRECT3DTEXTURE9 iface) { DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetLOD(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -189,9 +199,10 @@ static DWORD WINAPI IDirect3DTexture9Impl_GetLevelCount(LPDIRECT3DTEXTURE9 iface DWORD ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = IWineD3DTexture_GetLevelCount(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -200,9 +211,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_SetAutoGenFilterType(LPDIRECT3DTEXTU HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_SetAutoGenFilterType(This->wineD3DTexture, (WINED3DTEXTUREFILTERTYPE) FilterType); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -211,9 +223,10 @@ static D3DTEXTUREFILTERTYPE WINAPI IDirect3DTexture9Impl_GetAutoGenFilterType(LP D3DTEXTUREFILTERTYPE ret; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); ret = (D3DTEXTUREFILTERTYPE) IWineD3DTexture_GetAutoGenFilterType(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return ret; } @@ -221,38 +234,34 @@ static void WINAPI IDirect3DTexture9Impl_GenerateMipSubLevels(LPDIRECT3DTEXTURE9 IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DTexture_GenerateMipSubLevels(This->wineD3DTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } /* IDirect3DTexture9 Interface follow: */ static HRESULT WINAPI IDirect3DTexture9Impl_GetLevelDesc(LPDIRECT3DTEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - HRESULT hr; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; + HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; /* required for d3d8 */ - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } @@ -263,13 +272,15 @@ static HRESULT WINAPI IDirect3DTexture9Impl_GetSurfaceLevel(LPDIRECT3DTEXTURE9 i IWineD3DSurface *mySurface = NULL; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DTexture_GetSurfaceLevel(This->wineD3DTexture, Level, &mySurface); if (hrc == D3D_OK && NULL != ppSurfaceLevel) { IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppSurfaceLevel); IWineD3DSurface_Release(mySurface); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hrc; } @@ -278,9 +289,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_LockRect(LPDIRECT3DTEXTURE9 iface, U HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_LockRect(This->wineD3DTexture, Level, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -289,9 +301,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_UnlockRect(LPDIRECT3DTEXTURE9 iface, HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_UnlockRect(This->wineD3DTexture, Level); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -300,9 +313,10 @@ static HRESULT WINAPI IDirect3DTexture9Impl_AddDirtyRect(LPDIRECT3DTEXTURE9 ifac HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DTexture_AddDirtyRect(This->wineD3DTexture, pDirtyRect); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -343,7 +357,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9EX iface, U IDirect3DTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; - + TRACE("(%p) : W(%d) H(%d), Lvl(%d) d(%d), Fmt(%#x), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool); /* Allocate the storage for the device */ @@ -356,12 +370,14 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9EX iface, U object->lpVtbl = &Direct3DTexture9_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); - if (FAILED(hrc)) { + wined3d_mutex_unlock(); + if (FAILED(hrc)) + { /* free up object */ WARN("(%p) call to IWineD3DDevice_CreateTexture failed\n", This); HeapFree(GetProcessHeap(), 0, object); diff --git a/reactos/dll/directx/wine/d3d9/vertexbuffer.c b/reactos/dll/directx/wine/d3d9/vertexbuffer.c index 501db41439b..226e1139b81 100644 --- a/reactos/dll/directx/wine/d3d9/vertexbuffer.c +++ b/reactos/dll/directx/wine/d3d9/vertexbuffer.c @@ -58,9 +58,10 @@ static ULONG WINAPI IDirect3DVertexBuffer9Impl_Release(LPDIRECT3DVERTEXBUFFER9 i TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DBuffer_Release(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -74,14 +75,15 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetDevice(LPDIRECT3DVERTEXBUFFE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDevice(This->wineD3DVertexBuffer, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -91,9 +93,9 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_SetPrivateData(LPDIRECT3DVERTEX TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_SetPrivateData(This->wineD3DVertexBuffer, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -103,9 +105,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetPrivateData(LPDIRECT3DVERTEX HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetPrivateData(This->wineD3DVertexBuffer, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -114,9 +117,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_FreePrivateData(LPDIRECT3DVERTE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_FreePrivateData(This->wineD3DVertexBuffer, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -125,9 +129,10 @@ static DWORD WINAPI IDirect3DVertexBuffer9Impl_SetPriority(LPDIRECT3DVERTEXBUFFE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_SetPriority(This->wineD3DVertexBuffer, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -136,9 +141,10 @@ static DWORD WINAPI IDirect3DVertexBuffer9Impl_GetPriority(LPDIRECT3DVERTEXBUFFE HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetPriority(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -146,10 +152,9 @@ static void WINAPI IDirect3DVertexBuffer9Impl_PreLoad(LPDIRECT3DVERTEXBUFFER9 if IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DBuffer_PreLoad(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d9_cs); - return ; + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DVertexBuffer9Impl_GetType(LPDIRECT3DVERTEXBUFFER9 iface) { @@ -165,9 +170,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_Lock(LPDIRECT3DVERTEXBUFFER9 if HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Map(This->wineD3DVertexBuffer, OffsetToLock, SizeToLock, (BYTE **)ppbData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -176,9 +182,10 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_Unlock(LPDIRECT3DVERTEXBUFFER9 HRESULT hr; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_Unmap(This->wineD3DVertexBuffer); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -188,9 +195,9 @@ static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetDesc(LPDIRECT3DVERTEXBUFFER9 WINED3DBUFFER_DESC desc; TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DBuffer_GetDesc(This->wineD3DVertexBuffer, &desc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (SUCCEEDED(hr)) { pDesc->Format = D3DFMT_VERTEXDATA; @@ -228,10 +235,9 @@ static const IDirect3DVertexBuffer9Vtbl Direct3DVertexBuffer9_Vtbl = /* IDirect3DDevice9 IDirect3DVertexBuffer9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9EX iface, - UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, - IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) { - +HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT Size, DWORD Usage, + DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) +{ IDirect3DVertexBuffer9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; @@ -246,11 +252,12 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9EX iface object->lpVtbl = &Direct3DVertexBuffer9_Vtbl; object->ref = 1; object->fvf = FVF; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage & WINED3DUSAGE_MASK, 0 /* fvf for ddraw only */, (WINED3DPOOL) Pool, &(object->wineD3DVertexBuffer), (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); - + wined3d_mutex_unlock(); + if (hrc != D3D_OK) { /* free up object */ diff --git a/reactos/dll/directx/wine/d3d9/vertexdeclaration.c b/reactos/dll/directx/wine/d3d9/vertexdeclaration.c index 38f0751bb3f..4ae475194de 100644 --- a/reactos/dll/directx/wine/d3d9/vertexdeclaration.c +++ b/reactos/dll/directx/wine/d3d9/vertexdeclaration.c @@ -87,8 +87,7 @@ HRESULT vdecl_convert_fvf( /* convert the declaration */ elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(D3DVERTEXELEMENT9)); - if (!elements) - return D3DERR_OUTOFVIDEOMEMORY; + if (!elements) return D3DERR_OUTOFVIDEOMEMORY; elements[size-1] = end_element; idx = 0; @@ -230,9 +229,11 @@ void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) /* Should not happen unless wine has a bug or the application releases references it does not own */ ERR("Destroying vdecl with ref != 0\n"); } - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This->elements); HeapFree(GetProcessHeap(), 0, This); } @@ -262,13 +263,14 @@ static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDevice(LPDIRECT3DVERTEX TRACE("(%p) : Relay\n", iface); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVertexDeclaration_GetDevice(This->wineD3DVertexDeclaration, &myDevice); if (hr == D3D_OK && myDevice != NULL) { hr = IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); IWineD3DDevice_Release(myDevice); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -348,8 +350,9 @@ static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elem } /* IDirect3DDevice9 IDirect3DVertexDeclaration9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9EX iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) { - +HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(IDirect3DDevice9Ex *iface, + const D3DVERTEXELEMENT9 *pVertexElements, IDirect3DVertexDeclaration9 **ppDecl) +{ IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DVertexDeclaration9Impl *object = NULL; WINED3DVERTEXELEMENT* wined3d_elements; @@ -392,10 +395,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9E CopyMemory(object->elements, pVertexElements, element_count * sizeof(D3DVERTEXELEMENT9)); object->element_count = element_count; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_CreateVertexDeclaration(This->WineD3DDevice, &object->wineD3DVertexDeclaration, (IUnknown *)object, wined3d_elements, wined3d_element_count); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); HeapFree(GetProcessHeap(), 0, wined3d_elements); @@ -421,9 +424,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9EX i TRACE("(%p) : Relay\n", iface); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, pDeclImpl == NULL ? NULL : pDeclImpl->wineD3DVertexDeclaration); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -439,7 +443,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9EX i } *ppDecl = NULL; - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_GetVertexDeclaration(This->WineD3DDevice, &pTest); if (hr == D3D_OK && NULL != pTest) { IWineD3DVertexDeclaration_GetParent(pTest, (IUnknown **)ppDecl); @@ -447,7 +452,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9EX i } else { *ppDecl = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + TRACE("(%p) : returning %p\n", This, *ppDecl); return hr; } diff --git a/reactos/dll/directx/wine/d3d9/vertexshader.c b/reactos/dll/directx/wine/d3d9/vertexshader.c index fd2837d53be..8a5d5bc3e22 100644 --- a/reactos/dll/directx/wine/d3d9/vertexshader.c +++ b/reactos/dll/directx/wine/d3d9/vertexshader.c @@ -56,9 +56,10 @@ static ULONG WINAPI IDirect3DVertexShader9Impl_Release(LPDIRECT3DVERTEXSHADER9 i TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVertexShader_Release(This->wineD3DVertexShader); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -72,7 +73,7 @@ static HRESULT WINAPI IDirect3DVertexShader9Impl_GetDevice(LPDIRECT3DVERTEXSHADE HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVertexShader_GetDevice(This->wineD3DVertexShader, &myDevice); if (WINED3D_OK == hr && myDevice != NULL) { hr = IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); @@ -80,7 +81,8 @@ static HRESULT WINAPI IDirect3DVertexShader9Impl_GetDevice(LPDIRECT3DVERTEXSHADE } else { *ppDevice = NULL; } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + TRACE("(%p) returning (%p)\n", This, *ppDevice); return hr; } @@ -90,9 +92,10 @@ static HRESULT WINAPI IDirect3DVertexShader9Impl_GetFunction(LPDIRECT3DVERTEXSHA HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVertexShader_GetFunction(This->wineD3DVertexShader, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -125,9 +128,11 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(LPDIRECT3DDEVICE9EX iface object->ref = 1; object->lpVtbl = &Direct3DVertexShader9_Vtbl; - EnterCriticalSection(&d3d9_cs); - hrc= IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, NULL /* declaration */, pFunction, &object->wineD3DVertexShader, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); + hrc= IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, pFunction, + NULL /* output signature */, &object->wineD3DVertexShader, (IUnknown *)object); + wined3d_mutex_unlock(); if (FAILED(hrc)) { @@ -150,9 +155,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(LPDIRECT3DDEVICE9EX iface, I HRESULT hrc = D3D_OK; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, pShader==NULL?NULL:((IDirect3DVertexShader9Impl *)pShader)->wineD3DVertexShader); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); TRACE("(%p) : returning hr(%u)\n", This, hrc); return hrc; @@ -164,7 +170,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9EX iface, I HRESULT hrc = D3D_OK; TRACE("(%p) : Relay device@%p\n", This, This->WineD3DDevice); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hrc = IWineD3DDevice_GetVertexShader(This->WineD3DDevice, &pShader); if (SUCCEEDED(hrc)) { @@ -182,7 +189,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(LPDIRECT3DDEVICE9EX iface, I { WARN("(%p) : Call to IWineD3DDevice_GetVertexShader failed %u (device %p)\n", This, hrc, This->WineD3DDevice); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + TRACE("(%p) : returning %p\n", This, *ppShader); return hrc; } @@ -198,9 +206,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9EX return D3DERR_INVALIDCALL; } - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -215,9 +224,11 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9EX } TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + + wined3d_mutex_lock(); hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -226,9 +237,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetVertexShaderConstantI(This->WineD3DDevice, Register, pConstantData, Vector4iCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -237,9 +249,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetVertexShaderConstantI(This->WineD3DDevice, Register, pConstantData, Vector4iCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -248,9 +261,10 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_SetVertexShaderConstantB(This->WineD3DDevice, Register, pConstantData, BoolCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } @@ -259,8 +273,9 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(LPDIRECT3DDEVICE9EX HRESULT hr; TRACE("(%p) : Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DDevice_GetVertexShaderConstantB(This->WineD3DDevice, Register, pConstantData, BoolCount); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + return hr; } diff --git a/reactos/dll/directx/wine/d3d9/volume.c b/reactos/dll/directx/wine/d3d9/volume.c index 93b06b53158..9f1252a15fe 100644 --- a/reactos/dll/directx/wine/d3d9/volume.c +++ b/reactos/dll/directx/wine/d3d9/volume.c @@ -72,9 +72,10 @@ static ULONG WINAPI IDirect3DVolume9Impl_Release(LPDIRECT3DVOLUME9 iface) { TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVolume_Release(This->wineD3DVolume); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, This); } @@ -89,13 +90,13 @@ static HRESULT WINAPI IDirect3DVolume9Impl_GetDevice(LPDIRECT3DVOLUME9 iface, ID TRACE("iface %p, ppDevice %p\n", iface, ppDevice); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVolume_GetDevice(This->wineD3DVolume, &myDevice); IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); IWineD3DDevice_Release(myDevice); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return D3D_OK; } @@ -106,11 +107,11 @@ static HRESULT WINAPI IDirect3DVolume9Impl_SetPrivateData(LPDIRECT3DVOLUME9 ifac TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_SetPrivateData(This->wineD3DVolume, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -121,11 +122,11 @@ static HRESULT WINAPI IDirect3DVolume9Impl_GetPrivateData(LPDIRECT3DVOLUME9 ifac TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_GetPrivateData(This->wineD3DVolume, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -136,11 +137,11 @@ static HRESULT WINAPI IDirect3DVolume9Impl_FreePrivateData(LPDIRECT3DVOLUME9 ifa TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_FreePrivateData(This->wineD3DVolume, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -167,29 +168,26 @@ static HRESULT WINAPI IDirect3DVolume9Impl_GetContainer(LPDIRECT3DVOLUME9 iface, static HRESULT WINAPI IDirect3DVolume9Impl_GetDesc(LPDIRECT3DVOLUME9 iface, D3DVOLUME_DESC* pDesc) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; WINED3DVOLUME_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - wined3ddesc.Depth = &pDesc->Depth; - - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_GetDesc(This->wineD3DVolume, &wined3ddesc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.Format); + pDesc->Type = wined3ddesc.Type; + pDesc->Usage = wined3ddesc.Usage; + pDesc->Pool = wined3ddesc.Pool; + pDesc->Width = wined3ddesc.Width; + pDesc->Height = wined3ddesc.Height; + pDesc->Depth = wined3ddesc.Depth; + } return hr; } @@ -200,12 +198,12 @@ static HRESULT WINAPI IDirect3DVolume9Impl_LockBox(LPDIRECT3DVOLUME9 iface, D3DL TRACE("(%p) relay %p %p %p %d\n", This, This->wineD3DVolume, pLockedVolume, pBox, Flags); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_LockBox(This->wineD3DVolume, (WINED3DLOCKED_BOX *)pLockedVolume, (const WINED3DBOX *)pBox, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -216,11 +214,11 @@ static HRESULT WINAPI IDirect3DVolume9Impl_UnlockBox(LPDIRECT3DVOLUME9 iface) { TRACE("(%p) relay %p\n", This, This->wineD3DVolume); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolume_UnlockBox(This->wineD3DVolume); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } diff --git a/reactos/dll/directx/wine/d3d9/volumetexture.c b/reactos/dll/directx/wine/d3d9/volumetexture.c index 07b686fe5a4..31b90bce62e 100644 --- a/reactos/dll/directx/wine/d3d9/volumetexture.c +++ b/reactos/dll/directx/wine/d3d9/volumetexture.c @@ -58,9 +58,10 @@ static ULONG WINAPI IDirect3DVolumeTexture9Impl_Release(LPDIRECT3DVOLUMETEXTURE9 TRACE("(%p) : ReleaseRef to %d\n", This, ref); if (ref == 0) { - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture, D3D9CB_DestroyVolume); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); + IDirect3DDevice9Ex_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } @@ -75,14 +76,14 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetDevice(LPDIRECT3DVOLUMETEXT TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DStateBlock_GetDevice(This->wineD3DVolumeTexture, &wined3d_device); if (SUCCEEDED(hr)) { IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice); IWineD3DDevice_Release(wined3d_device); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -93,11 +94,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_SetPrivateData(LPDIRECT3DVOLUM TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_SetPrivateData(This->wineD3DVolumeTexture, refguid, pData, SizeOfData, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -108,11 +109,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetPrivateData(LPDIRECT3DVOLUM TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_GetPrivateData(This->wineD3DVolumeTexture, refguid, pData, pSizeOfData); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -123,11 +124,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_FreePrivateData(LPDIRECT3DVOLU TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_FreePrivateData(This->wineD3DVolumeTexture, refguid); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -138,11 +139,11 @@ static DWORD WINAPI IDirect3DVolumeTexture9Impl_SetPriority(LPDIRECT3DVOLUMETEXT TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); priority = IWineD3DVolumeTexture_SetPriority(This->wineD3DVolumeTexture, PriorityNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return priority; } @@ -153,11 +154,11 @@ static DWORD WINAPI IDirect3DVolumeTexture9Impl_GetPriority(LPDIRECT3DVOLUMETEXT TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); priority = IWineD3DVolumeTexture_GetPriority(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return priority; } @@ -167,11 +168,11 @@ static void WINAPI IDirect3DVolumeTexture9Impl_PreLoad(LPDIRECT3DVOLUMETEXTURE9 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVolumeTexture_PreLoad(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } static D3DRESOURCETYPE WINAPI IDirect3DVolumeTexture9Impl_GetType(LPDIRECT3DVOLUMETEXTURE9 iface) { @@ -180,11 +181,11 @@ static D3DRESOURCETYPE WINAPI IDirect3DVolumeTexture9Impl_GetType(LPDIRECT3DVOLU TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); type = IWineD3DVolumeTexture_GetType(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return type; } @@ -196,11 +197,11 @@ static DWORD WINAPI IDirect3DVolumeTexture9Impl_SetLOD(LPDIRECT3DVOLUMETEXTURE9 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); lod = IWineD3DVolumeTexture_SetLOD(This->wineD3DVolumeTexture, LODNew); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return lod; } @@ -211,11 +212,11 @@ static DWORD WINAPI IDirect3DVolumeTexture9Impl_GetLOD(LPDIRECT3DVOLUMETEXTURE9 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); lod = IWineD3DVolumeTexture_GetLOD(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return lod; } @@ -226,11 +227,11 @@ static DWORD WINAPI IDirect3DVolumeTexture9Impl_GetLevelCount(LPDIRECT3DVOLUMETE TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); level_count = IWineD3DVolumeTexture_GetLevelCount(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return level_count; } @@ -241,11 +242,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_SetAutoGenFilterType(LPDIRECT3 TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_SetAutoGenFilterType(This->wineD3DVolumeTexture, (WINED3DTEXTUREFILTERTYPE) FilterType); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -256,11 +257,11 @@ static D3DTEXTUREFILTERTYPE WINAPI IDirect3DVolumeTexture9Impl_GetAutoGenFilterT TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); filter_type = (D3DTEXTUREFILTERTYPE)IWineD3DVolumeTexture_GetAutoGenFilterType(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return filter_type; } @@ -270,40 +271,37 @@ static void WINAPI IDirect3DVolumeTexture9Impl_GenerateMipSubLevels(LPDIRECT3DVO TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); IWineD3DVolumeTexture_GenerateMipSubLevels(This->wineD3DVolumeTexture); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); } /* IDirect3DVolumeTexture9 Interface follow: */ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetLevelDesc(LPDIRECT3DVOLUMETEXTURE9 iface, UINT Level, D3DVOLUME_DESC* pDesc) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; WINED3DVOLUME_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - wined3ddesc.Depth = &pDesc->Depth; - - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_GetLevelDesc(This->wineD3DVolumeTexture, Level, &wined3ddesc); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.Format); + pDesc->Type = wined3ddesc.Type; + pDesc->Usage = wined3ddesc.Usage; + pDesc->Pool = wined3ddesc.Pool; + pDesc->Width = wined3ddesc.Width; + pDesc->Height = wined3ddesc.Height; + pDesc->Depth = wined3ddesc.Depth; + } return hr; } @@ -315,7 +313,7 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetVolumeLevel(LPDIRECT3DVOLUM TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DVolumeTexture_GetVolumeLevel(This->wineD3DVolumeTexture, Level, &myVolume); if (hrc == D3D_OK && NULL != ppVolumeLevel) { @@ -323,7 +321,7 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetVolumeLevel(LPDIRECT3DVOLUM IWineD3DVolumeTexture_Release(myVolume); } - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hrc; } @@ -334,12 +332,12 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_LockBox(LPDIRECT3DVOLUMETEXTUR TRACE("(%p) Relay %p %p %p %d\n", This, This->wineD3DVolumeTexture, pLockedVolume, pBox,Flags); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_LockBox(This->wineD3DVolumeTexture, Level, (WINED3DLOCKED_BOX *)pLockedVolume, (const WINED3DBOX *)pBox, Flags); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -350,11 +348,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_UnlockBox(LPDIRECT3DVOLUMETEXT TRACE("(%p) Relay %p %d\n", This, This->wineD3DVolumeTexture, Level); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_UnlockBox(This->wineD3DVolumeTexture, Level); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -365,11 +363,11 @@ static HRESULT WINAPI IDirect3DVolumeTexture9Impl_AddDirtyBox(LPDIRECT3DVOLUMETE TRACE("(%p) Relay\n", This); - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hr = IWineD3DVolumeTexture_AddDirtyBox(This->wineD3DVolumeTexture, (CONST WINED3DBOX *)pDirtyBox); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); return hr; } @@ -407,11 +405,10 @@ static const IDirect3DVolumeTexture9Vtbl Direct3DVolumeTexture9_Vtbl = /* IDirect3DDevice9 IDirect3DVolumeTexture9 Methods follow: */ -HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9EX iface, - UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, - D3DFORMAT Format, D3DPOOL Pool, - IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) { - +HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(IDirect3DDevice9Ex *iface, + UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, + D3DPOOL Pool, IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle) +{ IDirect3DVolumeTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; @@ -428,13 +425,13 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9EX if object->lpVtbl = &Direct3DVolumeTexture9_Vtbl; object->ref = 1; - EnterCriticalSection(&d3d9_cs); + wined3d_mutex_lock(); hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels, Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DVolumeTexture, (IUnknown *)object); - LeaveCriticalSection(&d3d9_cs); + wined3d_mutex_unlock(); if (hrc != D3D_OK) { diff --git a/reactos/dll/directx/wine/ddraw/ddraw.c b/reactos/dll/directx/wine/ddraw/ddraw.c index 7011afa4004..0d1b6dda237 100644 --- a/reactos/dll/directx/wine/ddraw/ddraw.c +++ b/reactos/dll/directx/wine/ddraw/ddraw.c @@ -816,7 +816,7 @@ IDirectDrawImpl_GetDisplayMode(IDirectDraw7 *iface, EnterCriticalSection(&ddraw_cs); /* This seems sane */ - if(!DDSD) + if (!DDSD) { LeaveCriticalSection(&ddraw_cs); return DDERR_INVALIDPARAMS; @@ -841,7 +841,7 @@ IDirectDrawImpl_GetDisplayMode(IDirectDraw7 *iface, DDSD->dwSize = Size; DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE; DDSD->dwWidth = Mode.Width; - DDSD->dwHeight = Mode.Height; + DDSD->dwHeight = Mode.Height; DDSD->u2.dwRefreshRate = 60; DDSD->ddsCaps.dwCaps = 0; DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat); @@ -1101,7 +1101,7 @@ IDirectDrawImpl_FlipToGDISurface(IDirectDraw7 *iface) * Returns: * Always returns DD_OK * - *****************************************************************************/ + *****************************************************************************/ static HRESULT WINAPI IDirectDrawImpl_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, @@ -1135,7 +1135,7 @@ IDirectDrawImpl_WaitForVerticalBlank(IDirectDraw7 *iface, * Returns: * Always returns DD_OK * - *****************************************************************************/ + *****************************************************************************/ static HRESULT WINAPI IDirectDrawImpl_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline) { IDirectDrawImpl *This = (IDirectDrawImpl *)iface; @@ -1155,7 +1155,7 @@ static HRESULT WINAPI IDirectDrawImpl_GetScanLine(IDirectDraw7 *iface, DWORD *Sc &Mode); /* Fake the line sweeping of the monitor */ - /* FIXME: We should synchronize with a source to keep the refresh rate */ + /* FIXME: We should synchronize with a source to keep the refresh rate */ *Scanline = This->cur_scanline++; /* Assume 20 scan lines in the vertical blank */ if (This->cur_scanline >= Mode.Height + 20) @@ -1176,7 +1176,7 @@ static HRESULT WINAPI IDirectDrawImpl_GetScanLine(IDirectDraw7 *iface, DWORD *Sc * DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET * if the state is not correct(See below) * - *****************************************************************************/ + *****************************************************************************/ static HRESULT WINAPI IDirectDrawImpl_TestCooperativeLevel(IDirectDraw7 *iface) { @@ -1187,8 +1187,8 @@ IDirectDrawImpl_TestCooperativeLevel(IDirectDraw7 *iface) EnterCriticalSection(&ddraw_cs); /* Description from MSDN: * For fullscreen apps return DDERR_NOEXCLUSIVEMODE if the user switched - * away from the app with e.g. alt-tab. Windowed apps receive - * DDERR_EXCLUSIVEMODEALREADYSET if another application created a + * away from the app with e.g. alt-tab. Windowed apps receive + * DDERR_EXCLUSIVEMODEALREADYSET if another application created a * DirectDraw object in exclusive mode. DDERR_WRONGMODE is returned, * when the video mode has changed */ @@ -1243,7 +1243,7 @@ IDirectDrawImpl_TestCooperativeLevel(IDirectDraw7 *iface) * DD_OK if the surface was found * DDERR_NOTFOUND if the GDI surface wasn't found * - *****************************************************************************/ + *****************************************************************************/ static HRESULT WINAPI IDirectDrawImpl_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface) @@ -1311,7 +1311,7 @@ IDirectDrawImpl_GetGDISurface(IDirectDraw7 *iface, * DD_OK on success * DDERR_INVALIDPARAMS if the callback wasn't set * - *****************************************************************************/ + *****************************************************************************/ static HRESULT WINAPI IDirectDrawImpl_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, @@ -1664,10 +1664,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, WINED3DSURFACE_DESC Desc; WINED3DFORMAT Format; - WINED3DRESOURCETYPE Type; DWORD Usage; WINED3DPOOL Pool; - UINT Size; WINED3DMULTISAMPLE_TYPE MultiSampleType; DWORD MultiSampleQuality; @@ -1702,19 +1700,17 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface_GetClipper(wineD3DSurface, &clipper); /* Get the surface properties */ - Desc.Format = &Format; - Desc.Type = &Type; - Desc.Usage = &Usage; - Desc.Pool = &Pool; - Desc.Size = &Size; - Desc.MultiSampleType = &MultiSampleType; - Desc.MultiSampleQuality = &MultiSampleQuality; - Desc.Width = &Width; - Desc.Height = &Height; - hr = IWineD3DSurface_GetDesc(wineD3DSurface, &Desc); if(hr != D3D_OK) return hr; + Format = Desc.format; + Usage = Desc.usage; + Pool = Desc.pool; + MultiSampleType = Desc.multisample_type; + MultiSampleQuality = Desc.multisample_quality; + Width = Desc.width; + Height = Desc.height; + if(swapchain) { /* If there's a swapchain, it owns the IParent interface. Create a new one for the * new surface @@ -1729,7 +1725,7 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, /* Create the new surface */ hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format, TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface, - Type, Usage, Pool, MultiSampleType, MultiSampleQuality, This->ImplType, Parent); + Usage, Pool, MultiSampleType, MultiSampleQuality, This->ImplType, Parent); if(hr != D3D_OK) return hr; @@ -1840,9 +1836,8 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, UINT level) { HRESULT hr; - UINT Width = 0, Height = 0; + UINT Width, Height; WINED3DFORMAT Format = WINED3DFMT_UNKNOWN; - WINED3DRESOURCETYPE ResType = WINED3DRTYPE_SURFACE; DWORD Usage = 0; WINED3DSURFTYPE ImplType = This->ImplType; WINED3DSURFACE_DESC Desc; @@ -1850,12 +1845,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, IParentImpl *parImpl = NULL; WINED3DPOOL Pool = WINED3DPOOL_DEFAULT; - /* Dummies for GetDesc */ - WINED3DPOOL dummy_d3dpool; - WINED3DMULTISAMPLE_TYPE dummy_mst; - UINT dummy_uint; - DWORD dummy_dword; - if (TRACE_ON(ddraw)) { TRACE(" (%p) Requesting surface desc :\n", This); @@ -1897,8 +1886,9 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, } else { - if((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE ) && - (This->ImplType != SURFACE_OPENGL ) && DefaultSurfaceType == SURFACE_UNKNOWN) + if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) + && (This->ImplType != SURFACE_OPENGL) + && DefaultSurfaceType == SURFACE_UNKNOWN) { /* We have to change to OpenGL, * and re-create all WineD3DSurfaces @@ -2026,8 +2016,8 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, /* Now create the WineD3D Surface */ hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format, - TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface, ResType, Usage, - Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType, Parent); + TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface, + Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType, Parent); if(hr != D3D_OK) { @@ -2058,16 +2048,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, * Don't use the Format choosen above, WineD3D might have * changed it */ - Desc.Format = &Format; - Desc.Type = &ResType; - Desc.Usage = &Usage; - Desc.Pool = &dummy_d3dpool; - Desc.Size = &dummy_uint; - Desc.MultiSampleType = &dummy_mst; - Desc.MultiSampleQuality = &dummy_dword; - Desc.Width = &Width; - Desc.Height = &Height; - (*ppSurf)->surface_desc.dwFlags |= DDSD_PIXELFORMAT; hr = IWineD3DSurface_GetDesc((*ppSurf)->WineD3DSurface, &Desc); if(hr != D3D_OK) @@ -2077,6 +2057,10 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, return hr; } + Format = Desc.format; + Width = Desc.width; + Height = Desc.height; + if(Format == WINED3DFMT_UNKNOWN) { FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n"); diff --git a/reactos/dll/directx/wine/ddraw/device.c b/reactos/dll/directx/wine/ddraw/device.c index 3b7778f69b6..09bc3e64391 100644 --- a/reactos/dll/directx/wine/ddraw/device.c +++ b/reactos/dll/directx/wine/ddraw/device.c @@ -94,7 +94,7 @@ static inline WORD d3d_fpu_setup(void) } /***************************************************************************** - * IUnknown Methods. Common for Version 1, 2, 3 and 7 + * IUnknown Methods. Common for Version 1, 2, 3 and 7 *****************************************************************************/ /***************************************************************************** @@ -2558,7 +2558,6 @@ IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, @@ -2567,13 +2566,11 @@ IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface, if(hr == WINED3D_OK && tex) { - memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(hr)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } @@ -2642,7 +2639,7 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, { case D3DRENDERSTATE_TEXTUREMAG: { - WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_NONE; + WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_POINT; switch ((D3DTEXTUREFILTER) Value) { @@ -2666,7 +2663,7 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, case D3DRENDERSTATE_TEXTUREMIN: { - WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_NONE; + WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_POINT; WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE; switch ((D3DTEXTUREFILTER) Value) @@ -2678,11 +2675,11 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, tex_min = WINED3DTEXF_LINEAR; break; case D3DFILTER_MIPNEAREST: - tex_min = WINED3DTEXF_NONE; + tex_min = WINED3DTEXF_POINT; tex_mip = WINED3DTEXF_POINT; break; case D3DFILTER_MIPLINEAR: - tex_min = WINED3DTEXF_NONE; + tex_min = WINED3DTEXF_POINT; tex_mip = WINED3DTEXF_LINEAR; break; case D3DFILTER_LINEARMIPNEAREST: @@ -2833,7 +2830,6 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, @@ -2843,12 +2839,11 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, if(hr == WINED3D_OK && tex) { memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(hr)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } @@ -2961,7 +2956,7 @@ IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface, TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value); - if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX)) + if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX)) { TRACE("Unexpected Light State Type\n"); return DDERR_INVALIDPARAMS; @@ -3094,7 +3089,7 @@ IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface, TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value); - if (!LightStateType && (LightStateType > D3DLIGHTSTATE_COLORVERTEX)) + if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX)) { TRACE("Unexpected Light State Type\n"); return DDERR_INVALIDPARAMS; @@ -4507,7 +4502,7 @@ IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface, EnterCriticalSection(&ddraw_cs); hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf); - if( (hr != D3D_OK) || (!Surf) ) + if( (hr != D3D_OK) || (!Surf) ) { *Texture = NULL; LeaveCriticalSection(&ddraw_cs); @@ -4648,7 +4643,6 @@ IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; HRESULT result; @@ -4659,12 +4653,11 @@ IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, if(result == WINED3D_OK && tex) { memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(result)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } @@ -5309,7 +5302,7 @@ IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface, TRACE("(%p)->(%p): Relay!\n", This, Mat); EnterCriticalSection(&ddraw_cs); - /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */ + /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */ hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice, (WINED3DMATERIAL*) Mat); LeaveCriticalSection(&ddraw_cs); @@ -5944,8 +5937,8 @@ static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest, static void copy_mipmap_chain(IDirect3DDeviceImpl *device, IDirectDrawSurfaceImpl *dest, IDirectDrawSurfaceImpl *src, - POINT *DestPoint, - RECT *SrcRect) + const POINT *DestPoint, + const RECT *SrcRect) { IDirectDrawSurfaceImpl *src_level, *dest_level; IDirectDrawSurface7 *temp; diff --git a/reactos/dll/directx/wine/ddraw/direct3d.c b/reactos/dll/directx/wine/ddraw/direct3d.c index 9ce0d3664af..88d5f2f8507 100644 --- a/reactos/dll/directx/wine/ddraw/direct3d.c +++ b/reactos/dll/directx/wine/ddraw/direct3d.c @@ -1324,7 +1324,7 @@ IDirect3DImpl_GetCaps(IWineD3D *WineD3D, Desc7->dwStencilCaps &= ( D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT | - D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR | D3DSTENCILCAPS_TWOSIDED); + D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR); /* FVF caps ?*/ diff --git a/reactos/dll/directx/wine/ddraw/executebuffer.c b/reactos/dll/directx/wine/ddraw/executebuffer.c index 3ff794d93b8..996c558bad2 100644 --- a/reactos/dll/directx/wine/ddraw/executebuffer.c +++ b/reactos/dll/directx/wine/ddraw/executebuffer.c @@ -227,14 +227,14 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, } else if(lpDevice->Handles[ci->u2.dwArg[0] - 1].type != DDrawHandle_Matrix) { ERR("Handle %d is not a matrix handle\n", ci->u2.dwArg[0]); } else { - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_WORLD) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_WORLD) lpDevice->world = ci->u2.dwArg[0]; - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_VIEW) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_VIEW) lpDevice->view = ci->u2.dwArg[0]; - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_PROJECTION) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_PROJECTION) lpDevice->proj = ci->u2.dwArg[0]; IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)lpDevice, - ci->u1.drstRenderStateType, (LPD3DMATRIX)lpDevice->Handles[ci->u2.dwArg[0] - 1].ptr); + ci->u1.dtstTransformStateType, (LPD3DMATRIX)lpDevice->Handles[ci->u2.dwArg[0] - 1].ptr); } instr += size; } @@ -249,7 +249,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, TRACE("(%08x,%08x)\n", ci->u1.dlstLightStateType, ci->u2.dwArg[0]); - if (!ci->u1.dlstLightStateType && (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX)) + if (!ci->u1.dlstLightStateType || (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX)) ERR("Unexpected Light State Type\n"); else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) { DWORD matHandle = ci->u2.dwArg[0]; @@ -317,7 +317,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, for (i = 0; i < count; i++) { LPD3DSTATE ci = (LPD3DSTATE) instr; - + IDirect3DDevice2_SetRenderState(d3d_device2, ci->u1.drstRenderStateType, ci->u2.dwArg[0]); instr += size; @@ -369,33 +369,33 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, TRACE("UPDATEEXTENTS "); TRACE("\n"); } - + /* This is where doing Direct3D on top on OpenGL is quite difficult. This method transforms a set of vertices using the CURRENT state (lighting, projection, ...) but does not rasterize them. They will only be put on screen later (with the POINT / LINE and TRIANGLE op-codes). The problem is that you can have a triangle with each point having been transformed using another state... - + In this implementation, I will emulate only ONE thing : each vertex can have its own "WORLD" transformation (this is used in the TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the execute buffer use the same state. - + If I find applications that change other states, I will try to do a more 'fine-tuned' state emulation (but I may become quite tricky if it changes a light position in the middle of a triangle). - + In this case, a 'direct' approach (i.e. without using OpenGL, but writing our own 3D rasterizer) would be easier. */ - + /* The current method (with the hypothesis that only the WORLD matrix will change between two points) is like this : - I transform 'manually' all the vertices with the current WORLD matrix and store them in the vertex buffer - during the rasterization phase, the WORLD matrix will be set to the Identity matrix */ - + /* Enough for the moment */ if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) { unsigned int nb; @@ -439,7 +439,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, src++; dst++; - + } } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) { unsigned int nb; @@ -465,7 +465,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, dst->u6.specular = src->u5.specular; dst->u7.tu = src->u6.tu; dst->u8.tv = src->u7.tv; - + /* Now, the matrix multiplication */ dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41); dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42); @@ -551,7 +551,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, for (i = 0; i < count; i++) { LPD3DSTATUS ci = (LPD3DSTATUS) instr; - + This->data.dsStatus = *ci; instr += size; @@ -705,7 +705,7 @@ IDirect3DExecuteBufferImpl_Lock(IDirect3DExecuteBuffer *iface, dwSize = lpDesc->dwSize; memset(lpDesc, 0, dwSize); memcpy(lpDesc, &This->desc, dwSize); - + if (TRACE_ON(d3d7)) { TRACE(" Returning description :\n"); _dump_D3DEXECUTEBUFFERDESC(lpDesc); @@ -756,7 +756,7 @@ IDirect3DExecuteBufferImpl_SetExecuteData(IDirect3DExecuteBuffer *iface, /* Get the number of vertices in the execute buffer */ nbvert = This->data.dwVertexCount; - + /* Prepares the transformed vertex buffer */ HeapFree(GetProcessHeap(), 0, This->vertex_data); This->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(D3DTLVERTEX)); diff --git a/reactos/dll/directx/wine/ddraw/light.c b/reactos/dll/directx/wine/ddraw/light.c index 4a759eb2463..030dcf030c4 100644 --- a/reactos/dll/directx/wine/ddraw/light.c +++ b/reactos/dll/directx/wine/ddraw/light.c @@ -179,17 +179,17 @@ IDirect3DLightImpl_SetLight(IDirect3DLight *iface, if ( (lpLight->dltType == 0) || (lpLight->dltType > D3DLIGHT_PARALLELPOINT) ) return DDERR_INVALIDPARAMS; - + if ( lpLight->dltType == D3DLIGHT_PARALLELPOINT ) - FIXME("D3DLIGHT_PARALLELPOINT no supported\n"); - + FIXME("D3DLIGHT_PARALLELPOINT no supported\n"); + /* Translate D3DLIGH2 structure to D3DLIGHT7 */ light7->dltType = lpLight->dltType; light7->dcvDiffuse = lpLight->dcvColor; - if ((((LPD3DLIGHT2)lpLight)->dwFlags & D3DLIGHT_NO_SPECULAR) != 0) + if ((((LPD3DLIGHT2)lpLight)->dwFlags & D3DLIGHT_NO_SPECULAR) != 0) light7->dcvSpecular = lpLight->dcvColor; else - light7->dcvSpecular = *(const D3DCOLORVALUE*)zero_value; + light7->dcvSpecular = *(const D3DCOLORVALUE*)zero_value; light7->dcvAmbient = lpLight->dcvColor; light7->dvPosition = lpLight->dvPosition; light7->dvDirection = lpLight->dvDirection; @@ -204,7 +204,7 @@ IDirect3DLightImpl_SetLight(IDirect3DLight *iface, EnterCriticalSection(&ddraw_cs); memcpy(&This->light, lpLight, lpLight->dwSize); if ((This->light.dwFlags & D3DLIGHT_ACTIVE) != 0) { - This->update(This); + This->update(This); } LeaveCriticalSection(&ddraw_cs); return D3D_OK; @@ -274,7 +274,7 @@ void light_activate(IDirect3DLightImpl* This) if (!This->active_viewport || !This->active_viewport->active_device) return; device = This->active_viewport->active_device; - + light_update(This); /* If was not active, activate it */ if ((This->light.dwFlags & D3DLIGHT_ACTIVE) == 0) { @@ -299,7 +299,7 @@ void light_desactivate(IDirect3DLightImpl* This) if (!This->active_viewport || !This->active_viewport->active_device) return; device = This->active_viewport->active_device; - + /* If was not active, activate it */ if ((This->light.dwFlags & D3DLIGHT_ACTIVE) != 0) { IDirect3DDevice7_LightEnable((IDirect3DDevice7 *)device, This->dwLightIndex, FALSE); diff --git a/reactos/dll/directx/wine/ddraw/parent.c b/reactos/dll/directx/wine/ddraw/parent.c index ec4cfde7cfd..473152ed740 100644 --- a/reactos/dll/directx/wine/ddraw/parent.c +++ b/reactos/dll/directx/wine/ddraw/parent.c @@ -117,8 +117,7 @@ IParentImpl_AddRef(IParent *iface) * The new refcount * *****************************************************************************/ -static ULONG WINAPI -IParentImpl_Release(IParent *iface) +static ULONG WINAPI IParentImpl_Release(IParent *iface) { IParentImpl *This = (IParentImpl *)iface; ULONG ref = InterlockedDecrement(&This->ref); diff --git a/reactos/dll/directx/wine/ddraw/surface.c b/reactos/dll/directx/wine/ddraw/surface.c index 14fc721ca3e..6d92c0d837c 100644 --- a/reactos/dll/directx/wine/ddraw/surface.c +++ b/reactos/dll/directx/wine/ddraw/surface.c @@ -920,9 +920,6 @@ IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This, IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice); } - /* MSDN: - * "This method increments the reference count of the surface being attached." - */ IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)Surf); LeaveCriticalSection(&ddraw_cs); return DD_OK; @@ -1033,7 +1030,7 @@ IDirectDrawSurfaceImpl_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface; TRACE("(%p)->(%p)\n",This,Rect); - /* MSDN says it's not implemented. I could forward it to WineD3D, + /* MSDN says it's not implemented. I could forward it to WineD3D, * then we'd implement it, but I don't think that's a good idea * (Stefan Dösinger) */ diff --git a/reactos/dll/directx/wine/ddraw/utils.c b/reactos/dll/directx/wine/ddraw/utils.c index 18114922485..17b4d34defa 100644 --- a/reactos/dll/directx/wine/ddraw/utils.c +++ b/reactos/dll/directx/wine/ddraw/utils.c @@ -349,7 +349,7 @@ PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, WINED3DFORMAT PixelFormat_DD2WineD3D(const DDPIXELFORMAT *DDPixelFormat) { - TRACE("Convert a DirectDraw Pixelformat to a WineD3D Pixelformat\n"); + TRACE("Convert a DirectDraw Pixelformat to a WineD3D Pixelformat\n"); if(TRACE_ON(ddraw)) { DDRAW_dump_pixelformat(DDPixelFormat); diff --git a/reactos/dll/directx/wine/ddraw/viewport.c b/reactos/dll/directx/wine/ddraw/viewport.c index c6e346e2294..9b0698903f5 100644 --- a/reactos/dll/directx/wine/ddraw/viewport.c +++ b/reactos/dll/directx/wine/ddraw/viewport.c @@ -84,7 +84,7 @@ void viewport_activate(IDirect3DViewportImpl* This, BOOL ignore_lights) { vp.dvMinZ = This->viewports.vp1.dvMinZ; vp.dvMaxZ = This->viewports.vp1.dvMaxZ; } - + /* And also set the viewport */ IDirect3DDevice7_SetViewport((IDirect3DDevice7 *)This->active_device, &vp); } @@ -657,11 +657,8 @@ IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3 *iface, * The return value of IDirect3DDevice7::Clear * *****************************************************************************/ -static HRESULT WINAPI -IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface, - DWORD dwCount, - D3DRECT *lpRects, - DWORD dwFlags) +static HRESULT WINAPI IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface, + DWORD dwCount, D3DRECT *lpRects, DWORD dwFlags) { IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface; DWORD color = 0x00000000; @@ -679,14 +676,15 @@ IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface, EnterCriticalSection(&ddraw_cs); if (dwFlags & D3DCLEAR_TARGET) { if (This->background == NULL) { - ERR(" Trying to clear the color buffer without background material !\n"); - } else { - color = - ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) | - ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8) | - ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0) | - ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24); - } + ERR(" Trying to clear the color buffer without background material !\n"); + } + else + { + color = ((int)((This->background->mat.u.diffuse.u1.r) * 255) << 16) + | ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8) + | ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0) + | ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24); + } } /* Need to temporarily activate viewport to clear it. Previously active one will be restored @@ -729,7 +727,7 @@ IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface, IDirect3DLightImpl *lpDirect3DLightImpl = (IDirect3DLightImpl *)lpDirect3DLight; DWORD i = 0; DWORD map = This->map_lights; - + TRACE("(%p)->(%p)\n", This, lpDirect3DLight); EnterCriticalSection(&ddraw_cs); @@ -755,7 +753,7 @@ IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface, /* Attach the light to the viewport */ lpDirect3DLightImpl->active_viewport = This; - + /* If active, activate the light */ if (This->active_device != NULL) { lpDirect3DLightImpl->activate(lpDirect3DLightImpl); @@ -785,7 +783,7 @@ IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface, IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface; IDirect3DLightImpl *lpDirect3DLightImpl = (IDirect3DLightImpl *)lpDirect3DLight; IDirect3DLightImpl *cur_light, *prev_light = NULL; - + TRACE("(%p)->(%p)\n", This, lpDirect3DLight); EnterCriticalSection(&ddraw_cs); diff --git a/reactos/dll/directx/wine/wined3d/arb_program_shader.c b/reactos/dll/directx/wine/wined3d/arb_program_shader.c index 56ee162e232..dd3511314d3 100644 --- a/reactos/dll/directx/wine/wined3d/arb_program_shader.c +++ b/reactos/dll/directx/wine/wined3d/arb_program_shader.c @@ -41,48 +41,242 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d); #define GLINFO_LOCATION (*gl_info) -/* We have to subtract any other PARAMs that we might use in our shader programs. - * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1, - * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */ -#define ARB_SHADER_RESERVED_VS_CONSTS 3 +/* GL locking for state handlers is done by the caller. */ +static BOOL need_mova_const(IWineD3DBaseShader *shader, const struct wined3d_gl_info *gl_info) +{ + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) shader; + if(!This->baseShader.reg_maps.usesmova) return FALSE; + return !GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION); +} -/* The arb shader only loads the bump mapping environment matrix into the shader if it finds - * a free constant to do that, so only reduce the number of available constants by 2 for the fog states. - */ -#define ARB_SHADER_RESERVED_PS_CONSTS 2 +/* Returns TRUE if result.clip from GL_NV_vertex_program2 should be used and FALSE otherwise */ +static inline BOOL use_nv_clip(const struct wined3d_gl_info *gl_info) +{ + return GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION); +} + +static BOOL need_helper_const(const struct wined3d_gl_info *gl_info) +{ + if (!GL_SUPPORT(NV_VERTEX_PROGRAM) /* Need to init colors. */ + || gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT /* Load the immval offset. */ + || gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W /* Have to init texcoords. */ + || (!use_nv_clip(gl_info)) /* Init the clip texcoord */) + { + return TRUE; + } + return FALSE; +} + +static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const struct wined3d_gl_info *gl_info) +{ + unsigned int ret = 1; + /* We use one PARAM for the pos fixup, and in some cases one to load + * some immediate values into the shader + */ + if(need_helper_const(gl_info)) ret++; + if(need_mova_const(shader, gl_info)) ret++; + return ret; +} + +static inline BOOL ffp_clip_emul(IWineD3DStateBlockImpl *stateblock) +{ + return stateblock->lowest_disabled_stage < 7; +} /* 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) - ARB_SHADER_RESERVED_VS_CONSTS) +#define ARB_SHADER_PRIVCONST_BASE (GL_LIMITS(vshader_constantsF) - 1) #define ARB_SHADER_PRIVCONST_POS ARB_SHADER_PRIVCONST_BASE + 0 /* ARB_program_shader private data */ -struct shader_arb_priv { + +struct control_frame +{ + struct list entry; + enum + { + IF, + IFC, + LOOP, + REP + } type; + BOOL muting; + BOOL outer_loop; + union + { + unsigned int loop_no; + unsigned int ifc_no; + }; + struct wined3d_shader_loop_control loop_control; + BOOL had_else; +}; + +struct arb_ps_np2fixup_info +{ + struct ps_np2fixup_info super; + /* For ARB we need a offset value: + * With both GLSL and ARB mode the NP2 fixup information (the texture dimensions) are stored in a + * consecutive way (GLSL uses a uniform array). Since ARB doesn't know the notion of a "standalone" + * array we need an offset to the index inside the program local parameter array. */ + UINT offset; +}; + +struct arb_ps_compile_args +{ + struct ps_compile_args super; + DWORD bools; /* WORD is enough, use DWORD for alignment */ + unsigned char loop_ctrl[MAX_CONST_I][3]; +}; + +struct stb_const_desc +{ + unsigned char texunit; + UINT const_num; +}; + +struct arb_ps_compiled_shader +{ + struct arb_ps_compile_args args; + struct arb_ps_np2fixup_info np2fixup_info; + struct stb_const_desc bumpenvmatconst[MAX_TEXTURES]; + struct stb_const_desc luminanceconst[MAX_TEXTURES]; + UINT int_consts[MAX_CONST_I]; + GLuint prgId; + UINT ycorrection; + unsigned char numbumpenvmatconsts; + char num_int_consts; +}; + +struct arb_vs_compile_args +{ + struct vs_compile_args super; + union + { + struct + { + WORD bools; + char clip_control[2]; + } boolclip; + DWORD boolclip_compare; + }; + DWORD ps_signature; + union + { + unsigned char vertex_samplers[4]; + DWORD vertex_samplers_compare; + }; + unsigned char loop_ctrl[MAX_CONST_I][3]; +}; + +struct arb_vs_compiled_shader +{ + struct arb_vs_compile_args args; + GLuint prgId; + UINT int_consts[MAX_CONST_I]; + char num_int_consts; + char need_color_unclamp; + UINT pos_fixup; +}; + +struct recorded_instruction +{ + struct wined3d_shader_instruction ins; + struct list entry; +}; + +struct shader_arb_ctx_priv +{ + char addr_reg[20]; + enum + { + /* plain GL_ARB_vertex_program or GL_ARB_fragment_program */ + ARB, + /* GL_NV_vertex_progam2_option or GL_NV_fragment_program_option */ + NV2, + /* GL_NV_vertex_program3 or GL_NV_fragment_program2 */ + NV3 + } target_version; + + const struct arb_vs_compile_args *cur_vs_args; + const struct arb_ps_compile_args *cur_ps_args; + const struct arb_ps_compiled_shader *compiled_fprog; + const struct arb_vs_compiled_shader *compiled_vprog; + struct arb_ps_np2fixup_info *cur_np2fixup_info; + struct list control_frames; + struct list record; + BOOL recording; + BOOL muted; + unsigned int num_loops, loop_depth, num_ifcs; + int aL; + + unsigned int vs_clipplanes; + BOOL footer_written; + BOOL in_main_func; + + /* For 3.0 vertex shaders */ + const char *vs_output[MAX_REG_OUTPUT]; + /* For 2.x and earlier vertex shaders */ + const char *texcrd_output[8], *color_output[2], *fog_output; + + /* 3.0 pshader input for compatibility with fixed function */ + const char *ps_input[MAX_REG_INPUT]; +}; + +struct ps_signature +{ + struct wined3d_shader_signature_element *sig; + DWORD idx; + struct wine_rb_entry entry; +}; + +struct arb_pshader_private { + struct arb_ps_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; + BOOL has_signature_idx; + DWORD input_signature_idx; + DWORD clipplane_emulation; + BOOL clamp_consts; +}; + +struct arb_vshader_private { + struct arb_vs_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; +}; + +struct shader_arb_priv +{ GLuint current_vprogram_id; GLuint current_fprogram_id; + const struct arb_ps_compiled_shader *compiled_fprog; + const struct arb_vs_compiled_shader *compiled_vprog; GLuint depth_blt_vprogram_id; GLuint depth_blt_fprogram_id[tex_type_count]; BOOL use_arbfp_fixed_func; - struct hash_table_t *fragment_shaders; + struct wine_rb_tree fragment_shaders; + BOOL last_ps_const_clamped; + BOOL last_vs_color_unclamp; + + struct wine_rb_tree signature_tree; + DWORD ps_sig_number; }; /******************************************************** * ARB_[vertex/fragment]_program helper functions follow ********************************************************/ -/** - * Loads floating point constants into the currently set ARB_vertex/fragment_program. +/* Loads floating point constants into the currently set ARB_vertex/fragment_program. * When constant_list == NULL, it will load all the constants. - * + * * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders) * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders) */ -static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts) { local_constant* lconst; - DWORD i, j; + DWORD i = 0, j; unsigned int ret; if (TRACE_ON(d3d_shader)) { @@ -97,54 +291,65 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, con if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1) { float lcl_const[4]; - for(i = 0; i < max_constants; i++) { + /* ps 1.x supports only 8 constants, clamp only those. When switching between 1.x and higher + * shaders, the first 8 constants are marked dirty for reload + */ + for(; i < min(8, max_constants); i++) { if(!dirty_consts[i]) continue; dirty_consts[i] = 0; 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; + if (constants[j + 0] > 1.0f) lcl_const[0] = 1.0f; + else if (constants[j + 0] < -1.0f) lcl_const[0] = -1.0f; else lcl_const[0] = constants[j + 0]; - if(constants[j + 1] > 1.0) lcl_const[1] = 1.0; - else if(constants[j + 1] < -1.0) lcl_const[1] = -1.0; + if (constants[j + 1] > 1.0f) lcl_const[1] = 1.0f; + else if (constants[j + 1] < -1.0f) lcl_const[1] = -1.0f; else lcl_const[1] = constants[j + 1]; - if(constants[j + 2] > 1.0) lcl_const[2] = 1.0; - else if(constants[j + 2] < -1.0) lcl_const[2] = -1.0; + if (constants[j + 2] > 1.0f) lcl_const[2] = 1.0f; + else if (constants[j + 2] < -1.0f) lcl_const[2] = -1.0f; else lcl_const[2] = constants[j + 2]; - if(constants[j + 3] > 1.0) lcl_const[3] = 1.0; - else if(constants[j + 3] < -1.0) lcl_const[3] = -1.0; + if (constants[j + 3] > 1.0f) lcl_const[3] = 1.0f; + else if (constants[j + 3] < -1.0f) lcl_const[3] = -1.0f; else lcl_const[3] = constants[j + 3]; GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); } - } else { - 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 */ + /* If further constants are dirty, reload them without clamping. + * + * The alternative is not to touch them, but then we cannot reset the dirty constant count + * to zero. That's bad for apps that only use PS 1.x shaders, because in that case the code + * above would always re-check the first 8 constants since max_constant remains at the init + * value + */ + } + + 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, i, max_constants, constants + (i * 4))); + */ + for(; 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; - 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))); - } + + GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4))); + } + } else { + for(; i < max_constants; i++) { + if(dirty_consts[i]) { + dirty_consts[i] = 0; + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); } } } @@ -180,93 +385,203 @@ static void shader_arb_load_np2fixup_constants( IWineD3DDevice* device, char usePixelShader, char useVertexShader) { - /* not implemented */ + + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl *) device; + const struct shader_arb_priv* const priv = (const struct shader_arb_priv *) deviceImpl->shader_priv; + IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; + + if (!usePixelShader) { + /* NP2 texcoord fixup is (currently) only done for pixelshaders. */ + return; + } + + if (priv->compiled_fprog && priv->compiled_fprog->np2fixup_info.super.active) { + const struct arb_ps_np2fixup_info* const fixup = &priv->compiled_fprog->np2fixup_info; + UINT i; + WORD active = fixup->super.active; + GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS]; + + for (i = 0; active; active >>= 1, ++i) { + const unsigned char idx = fixup->super.idx[i]; + const IWineD3DTextureImpl* const tex = (const IWineD3DTextureImpl*) stateBlock->textures[i]; + GLfloat* tex_dim = &np2fixup_constants[(idx >> 1) * 4]; + + if (!(active & 1)) continue; + + if (!tex) { + FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n"); + continue; + } + + if (idx % 2) { + tex_dim[2] = tex->baseTexture.pow2Matrix[0]; tex_dim[3] = tex->baseTexture.pow2Matrix[5]; + } else { + tex_dim[0] = tex->baseTexture.pow2Matrix[0]; tex_dim[1] = tex->baseTexture.pow2Matrix[5]; + } + } + + for (i = 0; i < fixup->super.num_consts; ++i) { + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, + fixup->offset + i, &np2fixup_constants[i * 4])); + } + } +} + +/* GL locking is done by the caller. */ +static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl) +{ + const struct wined3d_context *context = context_get_current(); + IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned char i; + struct shader_arb_priv *priv = deviceImpl->shader_priv; + const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog; + + for(i = 0; i < gl_shader->numbumpenvmatconsts; i++) + { + int texunit = gl_shader->bumpenvmatconst[i].texunit; + + /* The state manager takes care that this function is always called if the bump env matrix changes */ + const float *data = (const float *)&stateBlock->textureState[texunit][WINED3DTSS_BUMPENVMAT00]; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->bumpenvmatconst[i].const_num, data)); + + if (gl_shader->luminanceconst[i].const_num != WINED3D_CONST_NUM_UNUSED) + { + /* 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 + */ + const float *scale = (const float *)&stateBlock->textureState[texunit][WINED3DTSS_BUMPENVLSCALE]; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->luminanceconst[i].const_num, scale)); + } + } + checkGLcall("Load bumpmap consts"); + + if(gl_shader->ycorrection != WINED3D_CONST_NUM_UNUSED) + { + /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen). + * ycorrection.y: -1.0(onscreen), 1.0(offscreen) + * ycorrection.z: 1.0 + * ycorrection.w: 0.0 + */ + float val[4]; + val[0] = context->render_offscreen ? 0.0f + : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height; + val[1] = context->render_offscreen ? 1.0f : -1.0f; + val[2] = 1.0f; + val[3] = 0.0f; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val)); + checkGLcall("y correction loading"); + } + + if(gl_shader->num_int_consts == 0) return; + + for(i = 0; i < MAX_CONST_I; i++) + { + if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED) + { + float val[4]; + val[0] = stateBlock->pixelShaderConstantI[4 * i]; + val[1] = stateBlock->pixelShaderConstantI[4 * i + 1]; + val[2] = stateBlock->pixelShaderConstantI[4 * i + 2]; + val[3] = -1.0f; + + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val)); + } + } + checkGLcall("Load ps int consts"); +} + +/* GL locking is done by the caller. */ +static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl) +{ + IWineD3DStateBlockImpl* stateBlock; + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; + unsigned char i; + struct shader_arb_priv *priv = deviceImpl->shader_priv; + const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog; + + /* Upload the position fixup */ + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->pos_fixup, deviceImpl->posFixup)); + + if(gl_shader->num_int_consts == 0) return; + + stateBlock = deviceImpl->stateBlock; + + for(i = 0; i < MAX_CONST_I; i++) + { + if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED) + { + float val[4]; + val[0] = stateBlock->vertexShaderConstantI[4 * i]; + val[1] = stateBlock->vertexShaderConstantI[4 * i + 1]; + val[2] = stateBlock->vertexShaderConstantI[4 * i + 2]; + val[3] = -1.0f; + + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val)); + } + } + checkGLcall("Load vs int consts"); } /** * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs. - * - * We only support float constants in ARB at the moment, so don't + * + * We only support float constants in ARB at the moment, so don't * worry about the Integers or Booleans */ -static void shader_arb_load_constants( - IWineD3DDevice* device, - char usePixelShader, - char useVertexShader) { - - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; - IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; - const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; - unsigned char i; +/* GL locking is done by the caller (state handler) */ +static void shader_arb_load_constants(const struct wined3d_context *context, char usePixelShader, char useVertexShader) +{ + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + IWineD3DStateBlockImpl* stateBlock = device->stateBlock; + const struct wined3d_gl_info *gl_info = context->gl_info; if (useVertexShader) { IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; /* Load DirectX 9 float constants for vertex shader */ - 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)); + device->highest_dirty_vs_const = shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB, + device->highest_dirty_vs_const, stateBlock->vertexShaderConstantF, context->vshader_const_dirty); + shader_arb_vs_local_constants(device); } if (usePixelShader) { - IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader; - IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader; /* Load DirectX 9 float constants for pixel shader */ - 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); - - for(i = 0; i < psi->numbumpenvmatconsts; i++) { - /* The state manager takes care that this function is always called if the bump env matrix changes - */ - const float *data = (const 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 != WINED3D_CONST_NUM_UNUSED) - { - /* 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 - */ - const float *scale = (const 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; - } - } + device->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, + device->highest_dirty_ps_const, stateBlock->pixelShaderConstantF, context->pshader_const_dirty); + shader_arb_ps_local_constants(device); } } static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct wined3d_context *context = context_get_current(); /* 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); + if (!context || ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice != This) return; + + memset(context->vshader_const_dirty + start, 1, sizeof(*context->vshader_const_dirty) * count); + This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count); } static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct wined3d_context *context = context_get_current(); /* 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); + if (!context || ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice != This) return; + + memset(context->pshader_const_dirty + start, 1, sizeof(*context->pshader_const_dirty) * count); + This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count); } static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This) @@ -277,7 +592,7 @@ static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This) if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) return NULL; - ret = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * This->baseShader.limits.temporary); + ret = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * This->baseShader.limits.constant_float); if(!ret) { ERR("Out of memory\n"); return NULL; @@ -290,83 +605,75 @@ static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This) } /* Generate the variable & register declarations for the ARB_vertex_program output target */ -static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps, - SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, DWORD *lconst_map) +static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps, + struct wined3d_shader_buffer *buffer, const struct wined3d_gl_info *gl_info, DWORD *lconst_map, + DWORD *num_clipplanes, struct shader_arb_ctx_priv *ctx) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; - DWORD i, cur; + DWORD i, next_local = 0; char pshader = shader_is_pshader_version(reg_maps->shader_version.type); - unsigned max_constantsF = min(This->baseShader.limits.constant_float, - (pshader ? GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS : - GL_LIMITS(vshader_constantsF) - ARB_SHADER_RESERVED_VS_CONSTS)); - UINT extra_constants_needed = 0; + unsigned max_constantsF; const local_constant *lconst; + DWORD map; - /* Temporary Output register */ - shader_addline(buffer, "TEMP TMP_OUT;\n"); + /* In pixel shaders, all private constants are program local, we don't need anything + * from program.env. Thus we can advertise the full set of constants in pixel shaders. + * If we need a private constant the GL implementation will squeeze it in somewhere + * + * With vertex shaders we need the posFixup and on some GL implementations 4 helper + * immediate values. The posFixup is loaded using program.env for now, so always + * subtract one from the number of constants. If the shader uses indirect addressing, + * account for the helper const too because we have to declare all availabke d3d constants + * and don't know which are actually used. + */ + if(pshader) { + max_constantsF = GL_LIMITS(pshader_constantsF); + } else { + if(This->baseShader.reg_maps.usesrelconstF) { + DWORD highest_constf = 0, clip_limit; + max_constantsF = GL_LIMITS(vshader_constantsF) - reserved_vs_const(iface, gl_info); + max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants); - for(i = 0; i < This->baseShader.limits.temporary; i++) { - if (reg_maps->temporary[i]) - shader_addline(buffer, "TEMP R%u;\n", i); - } - - for (i = 0; i < This->baseShader.limits.address; i++) { - if (reg_maps->address[i]) - shader_addline(buffer, "ADDRESS A%d;\n", i); - } - - for(i = 0; i < This->baseShader.limits.texcoord; i++) { - if (reg_maps->texcoord[i]) - shader_addline(buffer,"TEMP T%u;\n", i); - } - - /* Texture coordinate registers must be pre-loaded */ - for (i = 0; i < This->baseShader.limits.texcoord; i++) { - if (reg_maps->texcoord[i]) - shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i); - } - - 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 + extra_constants_needed < GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS) { - 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 && max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS) { - ((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"); + for(i = 0; i < This->baseShader.limits.constant_float; i++) + { + DWORD idx = i >> 5; + DWORD shift = i & 0x1f; + if(reg_maps->constf[idx] & (1 << shift)) highest_constf = i; } - } else { - FIXME("No free constant found to load environment bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n"); - } - ps->numbumpenvmatconsts = cur + 1; + clip_limit = GL_LIMITS(clipplanes); + if(ctx->target_version == ARB) clip_limit = min(clip_limit, 4); + *num_clipplanes = min(clip_limit, max_constantsF - highest_constf - 1); + max_constantsF -= *num_clipplanes; + if(*num_clipplanes < clip_limit) + { + WARN("Only %u clipplanes out of %u enabled\n", *num_clipplanes, GL_LIMITS(clipplanes)); + } + } + else + { + if(ctx->target_version >= NV2) *num_clipplanes = GL_LIMITS(clipplanes); + else *num_clipplanes = min(GL_LIMITS(clipplanes), 4); + max_constantsF = GL_LIMITS(vshader_constantsF); + } } - if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) { - shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n", - srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high); - shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n", - srgb_sub_high, 0.0, 0.0, 0.0); + for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "TEMP R%u;\n", i); + } + + for (i = 0, map = reg_maps->address; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "ADDRESS A%u;\n", i); + } + + if (pshader && reg_maps->shader_version.major == 1 && reg_maps->shader_version.minor <= 3) + { + for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "TEMP T%u;\n", i); + } } /* Load local constants using the program-local space, @@ -376,6 +683,7 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { shader_addline(buffer, "PARAM C%u = program.local[%u];\n", lconst->idx, lconst_map[lconst->idx]); + next_local = max(next_local, lconst_map[lconst->idx] + 1); } } @@ -399,6 +707,8 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh } } } + + return next_local; } static const char * const shift_tab[] = { @@ -424,14 +734,8 @@ static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *i const struct wined3d_shader_dst_param *dst, char *write_mask) { char *ptr = write_mask; - char vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); - if (vshader && dst->reg.type == WINED3DSPR_ADDR) - { - *ptr++ = '.'; - *ptr++ = 'x'; - } - else if (dst->write_mask != WINED3DSP_WRITEMASK_ALL) + if (dst->write_mask != WINED3DSP_WRITEMASK_ALL) { *ptr++ = '.'; if (dst->write_mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x'; @@ -476,73 +780,207 @@ static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param, *ptr = '\0'; } -static void shader_arb_get_register_name(IWineD3DBaseShader *iface, WINED3DSHADER_PARAM_REGISTER_TYPE register_type, - UINT register_idx, BOOL rel_addr, char *register_name, BOOL *is_color) +static void shader_arb_request_a0(const struct wined3d_shader_instruction *ins, const char *src) +{ + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + + if(strcmp(priv->addr_reg, src) == 0) return; + + strcpy(priv->addr_reg, src); + shader_addline(buffer, "ARL A0.x, %s;\n", src); +} + +static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins, + const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr); + +static void shader_arb_get_register_name(const struct wined3d_shader_instruction *ins, + const struct wined3d_shader_register *reg, char *register_name, BOOL *is_color) { /* oPos, oFog and oPts in D3D */ static const char * const rastout_reg_names[] = {"TMP_OUT", "result.fogcoord", "result.pointsize"}; - IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface; + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; BOOL pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); + struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; *is_color = FALSE; - switch (register_type) + switch (reg->type) { case WINED3DSPR_TEMP: - sprintf(register_name, "R%u", register_idx); + sprintf(register_name, "R%u", reg->idx); break; case WINED3DSPR_INPUT: if (pshader) { - if (register_idx == 0) strcpy(register_name, "fragment.color.primary"); - else strcpy(register_name, "fragment.color.secondary"); + if(This->baseShader.reg_maps.shader_version.major < 3) + { + if (reg->idx == 0) strcpy(register_name, "fragment.color.primary"); + else strcpy(register_name, "fragment.color.secondary"); + } + else + { + if(reg->rel_addr) + { + char rel_reg[50]; + shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg); + + if(strcmp(rel_reg, "**aL_emul**") == 0) + { + DWORD idx = ctx->aL + reg->idx; + if(idx < MAX_REG_INPUT) + { + strcpy(register_name, ctx->ps_input[idx]); + } + else + { + ERR("Pixel shader input register out of bounds: %u\n", idx); + sprintf(register_name, "out_of_bounds_%u", idx); + } + } + else if(This->baseShader.reg_maps.input_registers & 0x0300) + { + /* There are two ways basically: + * + * 1) Use the unrolling code that is used for loop emulation and unroll the loop. + * That means trouble if the loop also contains a breakc or if the control values + * aren't local constants. + * 2) Generate an if block that checks if aL.y < 8, == 8 or == 9 and selects the + * source dynamically. The trouble is that we cannot simply read aL.y because it + * is an ADDRESS register. We could however push it, load .zw with a value and use + * ADAC to load the condition code register and pop it again afterwards + */ + FIXME("Relative input register addressing with more than 8 registers\n"); + + /* This is better than nothing for now */ + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + else if(ctx->cur_ps_args->super.vp_mode != vertexshader) + { + /* This is problematic because we'd have to consult the ctx->ps_input strings + * for where to find the varying. Some may be "0.0", others can be texcoords or + * colors. This needs either a pipeline replacement to make the vertex shader feed + * proper varyings, or loop unrolling + * + * For now use the texcoords and hope for the best + */ + FIXME("Non-vertex shader varying input with indirect addressing\n"); + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + else + { + /* D3D supports indirect addressing only with aL in loop registers. The loop instruction + * pulls GL_NV_fragment_program2 in + */ + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + } + else + { + if(reg->idx < MAX_REG_INPUT) + { + strcpy(register_name, ctx->ps_input[reg->idx]); + } + else + { + ERR("Pixel shader input register out of bounds: %u\n", reg->idx); + sprintf(register_name, "out_of_bounds_%u", reg->idx); + } + } + } } else { - if (((IWineD3DVertexShaderImpl *)This)->cur_args->swizzle_map & (1 << register_idx)) *is_color = TRUE; - sprintf(register_name, "vertex.attrib[%u]", register_idx); + if (ctx->cur_vs_args->super.swizzle_map & (1 << reg->idx)) *is_color = TRUE; + sprintf(register_name, "vertex.attrib[%u]", reg->idx); } break; case WINED3DSPR_CONST: - if (!pshader && rel_addr) + if (!pshader && reg->rel_addr) { + BOOL aL = FALSE; + char rel_reg[50]; UINT rel_offset = ((IWineD3DVertexShaderImpl *)This)->rel_offset; - if (register_idx >= rel_offset) - sprintf(register_name, "C[A0.x + %u]", register_idx - rel_offset); + if(This->baseShader.reg_maps.shader_version.major < 2) { + sprintf(rel_reg, "A0.x"); + } else { + shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg); + if(ctx->target_version == ARB) { + if(strcmp(rel_reg, "**aL_emul**") == 0) { + aL = TRUE; + } else { + shader_arb_request_a0(ins, rel_reg); + sprintf(rel_reg, "A0.x"); + } + } + } + if(aL) + sprintf(register_name, "C[%u]", ctx->aL + reg->idx); + else if (reg->idx >= rel_offset) + sprintf(register_name, "C[%s + %u]", rel_reg, reg->idx - rel_offset); else - sprintf(register_name, "C[A0.x - %u]", -register_idx + rel_offset); + sprintf(register_name, "C[%s - %u]", rel_reg, -reg->idx + rel_offset); } else { if (This->baseShader.reg_maps.usesrelconstF) - sprintf(register_name, "C[%u]", register_idx); + sprintf(register_name, "C[%u]", reg->idx); else - sprintf(register_name, "C%u", register_idx); + sprintf(register_name, "C%u", reg->idx); } break; case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */ - if (pshader) sprintf(register_name, "T%u", register_idx); - else sprintf(register_name, "A%u", register_idx); + if (pshader) { + if(This->baseShader.reg_maps.shader_version.major == 1 && + This->baseShader.reg_maps.shader_version.minor <= 3) { + /* In ps <= 1.3, Tx is a temporary register as destination to all instructions, + * and as source to most instructions. For some instructions it is the texcoord + * input. Those instructions know about the special use + */ + sprintf(register_name, "T%u", reg->idx); + } else { + /* in ps 1.4 and 2.x Tx is always a (read-only) varying */ + sprintf(register_name, "fragment.texcoord[%u]", reg->idx); + } + } + else + { + if(This->baseShader.reg_maps.shader_version.major == 1 || ctx->target_version >= NV2) + { + sprintf(register_name, "A%u", reg->idx); + } + else + { + sprintf(register_name, "A%u_SHADOW", reg->idx); + } + } break; case WINED3DSPR_COLOROUT: - if (register_idx == 0) + if(ctx->cur_ps_args->super.srgb_correction && reg->idx == 0) { strcpy(register_name, "TMP_COLOR"); } else { - /* TODO: See GL_ARB_draw_buffers */ - FIXME("Unsupported write to render target %u\n", register_idx); - sprintf(register_name, "unsupported_register"); + if(ctx->cur_ps_args->super.srgb_correction) FIXME("sRGB correction on higher render targets\n"); + if(This->baseShader.reg_maps.highest_render_target > 0) + { + sprintf(register_name, "result.color[%u]", reg->idx); + } + else + { + strcpy(register_name, "result.color"); + } } break; case WINED3DSPR_RASTOUT: - sprintf(register_name, "%s", rastout_reg_names[register_idx]); + if(reg->idx == 1) sprintf(register_name, "%s", ctx->fog_output); + else sprintf(register_name, "%s", rastout_reg_names[reg->idx]); break; case WINED3DSPR_DEPTHOUT: @@ -550,19 +988,71 @@ static void shader_arb_get_register_name(IWineD3DBaseShader *iface, WINED3DSHADE break; case WINED3DSPR_ATTROUT: - if (pshader) sprintf(register_name, "oD[%u]", register_idx); - else if (register_idx == 0) strcpy(register_name, "result.color.primary"); - else strcpy(register_name, "result.color.secondary"); + /* case WINED3DSPR_OUTPUT: */ + if (pshader) sprintf(register_name, "oD[%u]", reg->idx); + else strcpy(register_name, ctx->color_output[reg->idx]); break; case WINED3DSPR_TEXCRDOUT: - if (pshader) sprintf(register_name, "oT[%u]", register_idx); - else sprintf(register_name, "result.texcoord[%u]", register_idx); + if (pshader) + { + sprintf(register_name, "oT[%u]", reg->idx); + } + else + { + if(This->baseShader.reg_maps.shader_version.major < 3) + { + strcpy(register_name, ctx->texcrd_output[reg->idx]); + } + else + { + strcpy(register_name, ctx->vs_output[reg->idx]); + } + } + break; + + case WINED3DSPR_LOOP: + if(ctx->target_version >= NV2) + { + /* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */ + if(pshader) sprintf(register_name, "A0.x"); + else sprintf(register_name, "aL.y"); + } + else + { + /* Unfortunately this code cannot return the value of ctx->aL here. An immediate value + * would be valid, but if aL is used for indexing(its only use), there's likely an offset, + * thus the result would be something like C[15 + 30], which is not valid in the ARB program + * grammar. So return a marker for the emulated aL and intercept it in constant and varying + * indexing + */ + sprintf(register_name, "**aL_emul**"); + } + + break; + + case WINED3DSPR_CONSTINT: + sprintf(register_name, "I%u", reg->idx); + break; + + case WINED3DSPR_MISCTYPE: + if(reg->idx == 0) + { + sprintf(register_name, "vpos"); + } + else if(reg->idx == 1) + { + sprintf(register_name, "fragment.facing.x"); + } + else + { + FIXME("Unknown MISCTYPE register index %u\n", reg->idx); + } break; default: - FIXME("Unhandled register type %#x[%u]\n", register_type, register_idx); - sprintf(register_name, "unrecognized_register[%u]", register_idx); + FIXME("Unhandled register type %#x[%u]\n", reg->type, reg->idx); + sprintf(register_name, "unrecognized_register[%u]", reg->idx); break; } } @@ -574,8 +1064,7 @@ static void shader_arb_get_dst_param(const struct wined3d_shader_instruction *in char write_mask[6]; BOOL is_color; - shader_arb_get_register_name(ins->ctx->shader, wined3d_dst->reg.type, - wined3d_dst->reg.idx, !!wined3d_dst->reg.rel_addr, register_name, &is_color); + shader_arb_get_register_name(ins, &wined3d_dst->reg, register_name, &is_color); strcpy(str, register_name); shader_arb_get_write_mask(ins, wined3d_dst, write_mask); @@ -598,8 +1087,8 @@ static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channe } } -static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD dst_mask, - const char *one, const char *two, struct color_fixup_desc fixup) +static void gen_color_correction(struct wined3d_shader_buffer *buffer, const char *reg, + DWORD dst_mask, const char *one, const char *two, struct color_fixup_desc fixup) { DWORD mask; @@ -650,14 +1139,63 @@ static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD d } } -static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx, - const char *dst_str, const char *coord_reg, BOOL projected, BOOL bias) +static const char *shader_arb_get_modifier(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + DWORD mod; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + if (!ins->dst_count) return ""; + + mod = ins->dst[0].modifiers; + + /* Silently ignore PARTIALPRECISION if its not supported */ + if(priv->target_version == ARB) mod &= ~WINED3DSPDM_PARTIALPRECISION; + + if(mod & WINED3DSPDM_MSAMPCENTROID) + { + FIXME("Unhandled modifier WINED3DSPDM_MSAMPCENTROID\n"); + mod &= ~WINED3DSPDM_MSAMPCENTROID; + } + + switch(mod) + { + case WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION: + return "H_SAT"; + + case WINED3DSPDM_SATURATE: + return "_SAT"; + + case WINED3DSPDM_PARTIALPRECISION: + return "H"; + + case 0: + return ""; + + default: + FIXME("Unknown modifiers 0x%08x\n", mod); + return ""; + } +} + +#define TEX_PROJ 0x1 +#define TEX_BIAS 0x2 +#define TEX_LOD 0x4 +#define TEX_DERIV 0x10 + +static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx, + const char *dst_str, const char *coord_reg, WORD flags, const char *dsx, const char *dsy) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; const char *tex_type; + BOOL np2_fixup = FALSE; IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + const char *mod; + BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type); + + /* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */ + if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS; switch(sampler_type) { case WINED3DSTT_1D: @@ -673,10 +1211,11 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD } if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { - const IWineD3DPixelShaderImpl* const ps = (const IWineD3DPixelShaderImpl*)This; - if(ps->cur_args->np2_fixup & (1 << sampler_idx)) { - FIXME("NP2 texcoord fixup is currently not implemented in ARB mode (use GLSL instead).\n"); - } + if (priv->cur_np2fixup_info->super.active & (1 << sampler_idx)) + { + if (flags) FIXME("Only ordinary sampling from NP2 textures is supported.\n"); + else np2_fixup = TRUE; + } } break; @@ -693,22 +1232,61 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD tex_type = ""; } - if (bias) { - /* Shouldn't be possible, but let's check for it */ - if(projected) FIXME("Biased and Projected texture sampling\n"); - /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */ - shader_addline(buffer, "TXB %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); - } else if (projected) { - shader_addline(buffer, "TXP %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); - } else { - shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); + /* TEX, TXL, TXD and TXP do not support the "H" modifier, + * so don't use shader_arb_get_modifier + */ + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) mod = "_SAT"; + else mod = ""; + + /* Fragment samplers always have indentity mapping */ + if(sampler_idx >= MAX_FRAGMENT_SAMPLERS) + { + sampler_idx = priv->cur_vs_args->vertex_samplers[sampler_idx - MAX_FRAGMENT_SAMPLERS]; } - if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) + if (flags & TEX_DERIV) + { + if(flags & TEX_PROJ) FIXME("Projected texture sampling with custom derivatives\n"); + if(flags & TEX_BIAS) FIXME("Biased texture sampling with custom derivatives\n"); + shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, + dsx, dsy,sampler_idx, tex_type); + } + else if(flags & TEX_LOD) + { + if(flags & TEX_PROJ) FIXME("Projected texture sampling with explicit lod\n"); + if(flags & TEX_BIAS) FIXME("Biased texture sampling with explicit lod\n"); + shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, + sampler_idx, tex_type); + } + else if (flags & TEX_BIAS) + { + /* Shouldn't be possible, but let's check for it */ + if(flags & TEX_PROJ) FIXME("Biased and Projected texture sampling\n"); + /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */ + shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + } + else if (flags & TEX_PROJ) + { + shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + } + else + { + if (np2_fixup) + { + const unsigned char idx = priv->cur_np2fixup_info->super.idx[sampler_idx]; + shader_addline(buffer, "MUL TA, np2fixup[%u].%s, %s;\n", idx >> 1, + (idx % 2) ? "zwxy" : "xyzw", coord_reg); + + shader_addline(buffer, "TEX%s %s, TA, texture[%u], %s;\n", mod, dst_str, sampler_idx, tex_type); + } + else + shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + } + + if (pshader) { - IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)ins->ctx->shader; gen_color_correction(buffer, dst_str, ins->dst[0].write_mask, - "one", "coefmul.x", ps->cur_args->color_fixup[sampler_idx]); + "one", "coefmul.x", priv->cur_ps_args->super.color_fixup[sampler_idx]); } } @@ -720,14 +1298,14 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in char regstr[256]; char swzstr[20]; int insert_line; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; /* Assume a new line will be added */ insert_line = 1; /* Get register name */ - shader_arb_get_register_name(ins->ctx->shader, src->reg.type, - src->reg.idx, !!src->reg.rel_addr, regstr, &is_color); + shader_arb_get_register_name(ins, &src->reg, regstr, &is_color); shader_arb_get_swizzle(src, is_color, swzstr); switch (src->modifiers) @@ -769,6 +1347,23 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in shader_addline(buffer, "RCP T%c, %s.w;\n", 'A' + tmpreg, regstr); shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg); break; + case WINED3DSPSM_ABS: + if(ctx->target_version >= NV2) { + sprintf(outregstr, "|%s%s|", regstr, swzstr); + insert_line = 0; + } else { + shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr); + } + break; + case WINED3DSPSM_ABSNEG: + if(ctx->target_version >= NV2) { + sprintf(outregstr, "-|%s%s|", regstr, swzstr); + } else { + shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr); + sprintf(outregstr, "-T%c%s", 'A' + tmpreg, swzstr); + } + insert_line = 0; + break; default: sprintf(outregstr, "%s%s", regstr, swzstr); insert_line = 0; @@ -781,106 +1376,116 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in static void pshader_hw_bem(const struct wined3d_shader_instruction *ins) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[2][50]; - char dst_wmask[20]; DWORD sampler_code = dst->reg.idx; - BOOL has_bumpmat = FALSE; - BOOL is_color; - int i; - for(i = 0; i < This->numbumpenvmatconsts; i++) { - if (This->bumpenvmatconst[i].const_num != WINED3D_CONST_NUM_UNUSED - && This->bumpenvmatconst[i].texunit == sampler_code) - { - has_bumpmat = TRUE; - break; - } - } + shader_arb_get_dst_param(ins, dst, dst_name); - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); - strcat(dst_name, dst_wmask); + /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed + * + * Keep in mind that src_name[1] can be "TB" and src_name[0] can be "TA" because modifiers like _x2 are valid + * with bem. So delay loading the first parameter until after the perturbation calculation which needs two + * temps is done. + */ + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); + shader_addline(buffer, "SWZ TA, bumpenvmat%d, x, z, 0, 0;\n", sampler_code); + shader_addline(buffer, "DP3 TC.r, TA, %s;\n", src_name[1]); + shader_addline(buffer, "SWZ TA, bumpenvmat%d, y, w, 0, 0;\n", sampler_code); + shader_addline(buffer, "DP3 TC.g, TA, %s;\n", src_name[1]); shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); - shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); + shader_addline(buffer, "ADD %s, %s, TC;\n", dst_name, src_name[0]); +} - if(has_bumpmat) { - /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ - 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%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]); - } else { - shader_addline(buffer, "MOV %s, %s;\n", dst_name, src_name[0]); +static DWORD negate_modifiers(DWORD mod, char *extra_char) +{ + *extra_char = ' '; + switch(mod) + { + case WINED3DSPSM_NONE: return WINED3DSPSM_NEG; + case WINED3DSPSM_NEG: return WINED3DSPSM_NONE; + case WINED3DSPSM_BIAS: return WINED3DSPSM_BIASNEG; + case WINED3DSPSM_BIASNEG: return WINED3DSPSM_BIAS; + case WINED3DSPSM_SIGN: return WINED3DSPSM_SIGNNEG; + case WINED3DSPSM_SIGNNEG: return WINED3DSPSM_SIGN; + case WINED3DSPSM_COMP: *extra_char = '-'; return WINED3DSPSM_COMP; + case WINED3DSPSM_X2: return WINED3DSPSM_X2NEG; + case WINED3DSPSM_X2NEG: return WINED3DSPSM_X2; + case WINED3DSPSM_DZ: *extra_char = '-'; return WINED3DSPSM_DZ; + case WINED3DSPSM_DW: *extra_char = '-'; return WINED3DSPSM_DW; + case WINED3DSPSM_ABS: return WINED3DSPSM_ABSNEG; + case WINED3DSPSM_ABSNEG: return WINED3DSPSM_ABS; } + FIXME("Unknown modifier %u\n", mod); + return mod; } static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_wmask[20]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[3][50]; - BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE; - BOOL is_color; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); + BOOL is_color; - /* FIXME: support output modifiers */ - - /* Handle output register */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); - - /* Generate input register names (with modifiers) */ - shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); + shader_arb_get_dst_param(ins, dst, dst_name); shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); - shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */ if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue) { - shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]); + shader_addline(buffer, "MOV%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[1]); } else { - shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]); - shader_addline(buffer, "CMP%s %s%s, TMP, %s, %s;\n", - sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1], src_name[2]); + struct wined3d_shader_src_param src0_copy = ins->src[0]; + char extra_neg; + + /* src0 may have a negate srcmod set, so we can't blindly add "-" to the name */ + src0_copy.modifiers = negate_modifiers(src0_copy.modifiers, &extra_neg); + + shader_arb_get_src_param(ins, &src0_copy, 0, src_name[0]); + shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); + shader_addline(buffer, "ADD TA, %c%s, coefdiv.x;\n", extra_neg, src_name[0]); + /* No modifiers supported on CMP */ + shader_addline(buffer, "CMP %s, TA, %s, %s;\n", dst_name, src_name[1], src_name[2]); + + /* _SAT on CMP doesn't make much sense, but it is not a pure NOP */ + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, dst_name); + } } } static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_wmask[20]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[3][50]; - BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE; BOOL is_color; - /* FIXME: support output modifiers */ - - /* Handle output register */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); + shader_arb_get_dst_param(ins, dst, dst_name); /* Generate input register names (with modifiers) */ shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); - shader_addline(buffer, "CMP%s %s%s, %s, %s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, + /* No modifiers are supported on CMP */ + shader_addline(buffer, "CMP %s, %s, %s, %s;\n", dst_name, src_name[0], src_name[2], src_name[1]); + + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name[0]); + } } /** Process the WINED3DSIO_DP2ADD instruction in ARB. @@ -888,37 +1493,64 @@ static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins) static void pshader_hw_dp2add(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_wmask[20]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[3][50]; - BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE; - BOOL is_color; - - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); + struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; + shader_arb_get_dst_param(ins, dst, dst_name); shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); - shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); shader_arb_get_src_param(ins, &ins->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]); - shader_addline(buffer, "MOV TMP.z, 0.0;\n"); - shader_addline(buffer, "DP3 TMP2, TMP, %s;\n", src_name[1]); - shader_addline(buffer, "ADD%s %s%s, TMP2, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[2]); + if(ctx->target_version >= NV3) + { + /* GL_NV_fragment_program2 has a 1:1 matching instruction */ + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); + shader_addline(buffer, "DP2A%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins), + dst_name, src_name[0], src_name[1], src_name[2]); + } + else if(ctx->target_version >= NV2) + { + /* dst.x = src2.?, src0.x, src1.x + src0.y * src1.y + * dst.y = src2.?, src0.x, src1.z + src0.y * src1.w + * dst.z = src2.?, src0.x, src1.x + src0.y * src1.y + * dst.z = src2.?, src0.x, src1.z + src0.y * src1.w + * + * Make sure that src1.zw = src1.xy, then we get a classic dp2add + * + * .xyxy and other swizzles that we could get with this are not valid in + * plain ARBfp, but luckily the NV extension grammar lifts this limitation. + */ + struct wined3d_shader_src_param tmp_param = ins->src[1]; + DWORD swizzle = tmp_param.swizzle & 0xf; /* Selects .xy */ + tmp_param.swizzle = swizzle | (swizzle << 4); /* Creates .xyxy */ + + shader_arb_get_src_param(ins, &tmp_param, 1, src_name[1]); + + shader_addline(buffer, "X2D%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins), + dst_name, src_name[2], src_name[0], src_name[1]); + } + else + { + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); + /* Emulate a DP2 with a DP3 and 0.0. Don't use the dest as temp register, it could be src[1] or src[2] + * src_name[0] can be TA, but TA is a private temp for modifiers, so it is save to overwrite + */ + shader_addline(buffer, "MOV TA, %s;\n", src_name[0]); + shader_addline(buffer, "MOV TA.z, 0.0;\n"); + shader_addline(buffer, "DP3 TA, TA, %s;\n", src_name[1]); + shader_addline(buffer, "ADD%s %s, TA, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[2]); + } } /* Map the opcode 1-to-1 to the GL code */ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; const char *instruction; char arguments[256], dst_str[50]; unsigned int i; const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - const char *modifier; switch (ins->handler_idx) { @@ -928,31 +1560,25 @@ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins) case WINED3DSIH_DP3: instruction = "DP3"; break; case WINED3DSIH_DP4: instruction = "DP4"; break; case WINED3DSIH_DST: instruction = "DST"; break; - case WINED3DSIH_EXP: instruction = "EX2"; break; - case WINED3DSIH_EXPP: instruction = "EXP"; break; case WINED3DSIH_FRC: instruction = "FRC"; break; case WINED3DSIH_LIT: instruction = "LIT"; break; - case WINED3DSIH_LOG: instruction = "LG2"; break; - case WINED3DSIH_LOGP: instruction = "LOG"; break; case WINED3DSIH_LRP: instruction = "LRP"; break; case WINED3DSIH_MAD: instruction = "MAD"; break; case WINED3DSIH_MAX: instruction = "MAX"; break; case WINED3DSIH_MIN: instruction = "MIN"; break; case WINED3DSIH_MOV: instruction = "MOV"; break; case WINED3DSIH_MUL: instruction = "MUL"; break; - case WINED3DSIH_POW: instruction = "POW"; break; case WINED3DSIH_SGE: instruction = "SGE"; break; case WINED3DSIH_SLT: instruction = "SLT"; break; case WINED3DSIH_SUB: instruction = "SUB"; break; + case WINED3DSIH_MOVA:instruction = "ARR"; break; + case WINED3DSIH_SGN: instruction = "SSG"; break; + case WINED3DSIH_DSX: instruction = "DDX"; break; default: instruction = ""; FIXME("Unhandled opcode %#x\n", ins->handler_idx); break; } - /* All instructions handled by this function have a destination parameter */ - if(dst->modifiers & WINED3DSPDM_SATURATE) modifier = "_SAT"; - else modifier = ""; - /* Note that shader_arb_add_dst_param() adds spaces. */ arguments[0] = '\0'; shader_arb_get_dst_param(ins, dst, dst_str); @@ -963,36 +1589,67 @@ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[i], i, operand); strcat(arguments, operand); } - shader_addline(buffer, "%s%s %s%s;\n", instruction, modifier, dst_str, arguments); + shader_addline(buffer, "%s%s %s%s;\n", instruction, shader_arb_get_modifier(ins), dst_str, arguments); } static void shader_hw_nop(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; shader_addline(buffer, "NOP;\n"); } static void shader_hw_mov(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + BOOL pshader = shader_is_pshader_version(shader->baseShader.reg_maps.shader_version.type); + struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; - if ((ins->ctx->reg_maps->shader_version.major == 1 - && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type) - && ins->dst[0].reg.type == WINED3DSPR_ADDR) - || ins->handler_idx == WINED3DSIH_MOVA) + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src0_param[256]; + + if(ins->handler_idx == WINED3DSIH_MOVA) { + char write_mask[6]; + + if(ctx->target_version >= NV2) { + shader_hw_map2gl(ins); + return; + } + shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param); + shader_arb_get_write_mask(ins, &ins->dst[0], write_mask); + + /* This implements the mova formula used in GLSL. The first two instructions + * prepare the sign() part. Note that it is fine to have my_sign(0.0) = 1.0 + * in this case: + * mova A0.x, 0.0 + * + * A0.x = arl(floor(abs(0.0) + 0.5) * 1.0) = floor(0.5) = 0.0 since arl does a floor + * + * The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into + * A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign. + */ + shader_addline(buffer, "SGE A0_SHADOW%s, %s, mova_const.y;\n", write_mask, src0_param); + shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, mova_const.z, -mova_const.w;\n", write_mask); + + shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param); + shader_addline(buffer, "ADD TA%s, TA, mova_const.x;\n", write_mask); + shader_addline(buffer, "FLR TA%s, TA;\n", write_mask); + if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) + { + shader_addline(buffer, "ADD TA%s, TA, helper_const.z;\n", write_mask); + } + shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask); + + ((struct shader_arb_ctx_priv *)ins->ctx->backend_data)->addr_reg[0] = '\0'; + } else if (ins->ctx->reg_maps->shader_version.major == 1 + && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type) + && ins->dst[0].reg.type == WINED3DSPR_ADDR) { - SHADER_BUFFER *buffer = ins->ctx->buffer; - char src0_param[256]; - - if (ins->handler_idx == WINED3DSIH_MOVA) - FIXME("mova should round\n"); - src0_param[0] = '\0'; if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) { shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param); - shader_addline(buffer, "ADD TMP.x, %s, helper_const.z;\n", src0_param); - shader_addline(buffer, "ARL A0.x, TMP.x;\n"); + shader_addline(buffer, "ADD TA.x, %s, helper_const.z;\n", src0_param); + shader_addline(buffer, "ARL A0.x, TA.x;\n"); } else { @@ -1005,6 +1662,16 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins) shader_addline(buffer, "ARL A0.x, %s;\n", src0_param); } } + else if(ins->dst[0].reg.type == WINED3DSPR_COLOROUT && ins->dst[0].reg.idx == 0 && pshader) + { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) shader; + if(ctx->cur_ps_args->super.srgb_correction && ps->color0_mov) + { + shader_addline(buffer, "#mov handled in srgb write code\n"); + return; + } + shader_hw_map2gl(ins); + } else { shader_hw_map2gl(ins); @@ -1014,7 +1681,7 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins) static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char reg_dest[40]; /* No swizzles are allowed in d3d's texkill. PS 1.x ignores the 4th component as documented, @@ -1024,14 +1691,42 @@ static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins) if (ins->ctx->reg_maps->shader_version.major >= 2) { - /* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */ - shader_addline(buffer, "KIL %s;\n", reg_dest); + const char *kilsrc = "TA"; + BOOL is_color; + + shader_arb_get_register_name(ins, &dst->reg, reg_dest, &is_color); + if(dst->write_mask == WINED3DSP_WRITEMASK_ALL) + { + kilsrc = reg_dest; + } + else + { + /* Sigh. KIL doesn't support swizzles/writemasks. KIL passes a writemask, but ".xy" for example + * is not valid as a swizzle in ARB (needs ".xyyy"). Use SWZ to load the register properly, and set + * masked out components to 0(won't kill) + */ + char x = '0', y = '0', z = '0', w = '0'; + if(dst->write_mask & WINED3DSP_WRITEMASK_0) x = 'x'; + if(dst->write_mask & WINED3DSP_WRITEMASK_1) y = 'y'; + if(dst->write_mask & WINED3DSP_WRITEMASK_2) z = 'z'; + if(dst->write_mask & WINED3DSP_WRITEMASK_3) w = 'w'; + shader_addline(buffer, "SWZ TA, %s, %c, %c, %c, %c;\n", reg_dest, x, y, z, w); + } + shader_addline(buffer, "KIL %s;\n", kilsrc); } else { /* ARB fp doesn't like swizzles on the parameter of the KIL instruction. To mask the 4th component, * copy the register into our general purpose TMP variable, overwrite .w and pass TMP to KIL + * + * ps_1_3 shaders use the texcoord incarnation of the Tx register. ps_1_4 shaders can use the same, + * or pass in any temporary register(in shader phase 2) */ - shader_addline(buffer, "SWZ TMP, %s, x, y, z, 1;\n", reg_dest); - shader_addline(buffer, "KIL TMP;\n"); + if(ins->ctx->reg_maps->shader_version.minor <= 3) { + sprintf(reg_dest, "fragment.texcoord[%u]", dst->reg.idx); + } else { + shader_arb_get_dst_param(ins, dst, reg_dest); + } + shader_addline(buffer, "SWZ TA, %s, x, y, z, 1;\n", reg_dest); + shader_addline(buffer, "KIL TA;\n"); } } @@ -1040,217 +1735,213 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins) IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - BOOL is_color; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); - BOOL projected = FALSE, bias = FALSE; + struct wined3d_shader_src_param src; char reg_dest[40]; char reg_coord[40]; DWORD reg_sampler_code; + DWORD myflags = 0; /* All versions have a destination register */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, reg_dest, &is_color); + shader_arb_get_dst_param(ins, dst, reg_dest); - /* 1.0-1.3: Use destination register as coordinate source. + /* 1.0-1.4: Use destination register number as texture code. + 2.0+: Use provided sampler number as texure code. */ + if (shader_version < WINED3D_SHADER_VERSION(2,0)) + reg_sampler_code = dst->reg.idx; + else + reg_sampler_code = ins->src[1].reg.idx; + + /* 1.0-1.3: Use the texcoord varying. 1.4+: Use provided coordinate source register. */ - if (shader_version < WINED3D_SHADER_VERSION(1,4)) - strcpy(reg_coord, reg_dest); - else - shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord); + if (shader_version < WINED3D_SHADER_VERSION(1,4)) + sprintf(reg_coord, "fragment.texcoord[%u]", reg_sampler_code); + else { + /* TEX is the only instruction that can handle DW and DZ natively */ + src = ins->src[0]; + if(src.modifiers == WINED3DSPSM_DW) src.modifiers = WINED3DSPSM_NONE; + if(src.modifiers == WINED3DSPSM_DZ) src.modifiers = WINED3DSPSM_NONE; + shader_arb_get_src_param(ins, &src, 0, reg_coord); + } - /* 1.0-1.4: Use destination register number as texture code. - 2.0+: Use provided sampler number as texure code. */ - if (shader_version < WINED3D_SHADER_VERSION(2,0)) - reg_sampler_code = dst->reg.idx; - else - reg_sampler_code = ins->src[1].reg.idx; - - /* projection flag: - * 1.1, 1.2, 1.3: Use WINED3DTSS_TEXTURETRANSFORMFLAGS - * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0] - * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode - */ - if (shader_version < WINED3D_SHADER_VERSION(1,4)) - { - DWORD flags = 0; - if(reg_sampler_code < MAX_TEXTURES) { - flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; - } - if (flags & WINED3DTTFF_PROJECTED) { - projected = TRUE; - } - } - else if (shader_version < WINED3D_SHADER_VERSION(2,0)) - { - DWORD src_mod = ins->src[0].modifiers; - if (src_mod == WINED3DSPSM_DZ) { - projected = TRUE; - } else if(src_mod == WINED3DSPSM_DW) { - projected = TRUE; - } - } else { - if (ins->flags & WINED3DSI_TEXLD_PROJECT) projected = TRUE; - if (ins->flags & WINED3DSI_TEXLD_BIAS) bias = TRUE; - } - shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, projected, bias); + /* projection flag: + * 1.1, 1.2, 1.3: Use WINED3DTSS_TEXTURETRANSFORMFLAGS + * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0] + * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode + */ + if (shader_version < WINED3D_SHADER_VERSION(1,4)) + { + DWORD flags = 0; + if(reg_sampler_code < MAX_TEXTURES) { + flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; + } + if (flags & WINED3DTTFF_PROJECTED) { + myflags |= TEX_PROJ; + } + } + else if (shader_version < WINED3D_SHADER_VERSION(2,0)) + { + DWORD src_mod = ins->src[0].modifiers; + if (src_mod == WINED3DSPSM_DZ) { + /* TXP cannot handle DZ natively, so move the z coordinate to .w. reg_coord is a read-only + * varying register, so we need a temp reg + */ + shader_addline(ins->ctx->buffer, "SWZ TA, %s, x, y, z, z;\n", reg_coord); + strcpy(reg_coord, "TA"); + myflags |= TEX_PROJ; + } else if(src_mod == WINED3DSPSM_DW) { + myflags |= TEX_PROJ; + } + } else { + if (ins->flags & WINED3DSI_TEXLD_PROJECT) myflags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) myflags |= TEX_BIAS; + } + shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, myflags, NULL, NULL); } static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); + char dst_str[50]; - char tmp[20]; - shader_arb_get_write_mask(ins, dst, tmp); - if (shader_version != WINED3D_SHADER_VERSION(1,4)) + if (shader_version < WINED3D_SHADER_VERSION(1,4)) { DWORD reg = dst->reg.idx; - shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg); + + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); + shader_addline(buffer, "MOV_SAT %s, fragment.texcoord[%u];\n", dst_str, reg); } else { char reg_src[40]; shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src); - shader_addline(buffer, "MOV R%u%s, %s;\n", dst->reg.idx, tmp, reg_src); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); + shader_addline(buffer, "MOV %s, %s;\n", dst_str, reg_src); } } static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD flags; DWORD reg1 = ins->dst[0].reg.idx; - char dst_str[8]; + char dst_str[50]; char src_str[50]; - sprintf(dst_str, "T%u", reg1); + /* Note that texreg2ar treats Tx as a temporary register, not as a varying */ + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src_str); - shader_addline(buffer, "MOV TMP.x, %s.w;\n", src_str); - shader_addline(buffer, "MOV TMP.y, %s.x;\n", src_str); + /* Move .x first in case src_str is "TA" */ + shader_addline(buffer, "MOV TA.y, %s.x;\n", src_str); + shader_addline(buffer, "MOV TA.x, %s.w;\n", src_str); flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg1, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg1, dst_str, "TA", flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); } static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; DWORD reg1 = ins->dst[0].reg.idx; - char dst_str[8]; + char dst_str[50]; char src_str[50]; - sprintf(dst_str, "T%u", reg1); + /* Note that texreg2gb treats Tx as a temporary register, not as a varying */ + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src_str); - shader_addline(buffer, "MOV TMP.x, %s.y;\n", src_str); - shader_addline(buffer, "MOV TMP.y, %s.z;\n", src_str); - shader_hw_sample(ins, reg1, dst_str, "TMP", FALSE, FALSE); + shader_addline(buffer, "MOV TA.x, %s.y;\n", src_str); + shader_addline(buffer, "MOV TA.y, %s.z;\n", src_str); + shader_hw_sample(ins, reg1, dst_str, "TA", 0, NULL, NULL); } static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins) { DWORD reg1 = ins->dst[0].reg.idx; - char dst_str[8]; + char dst_str[50]; char src_str[50]; - sprintf(dst_str, "T%u", reg1); + /* Note that texreg2rg treats Tx as a temporary register, not as a varying */ + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src_str); - shader_hw_sample(ins, reg1, dst_str, src_str, FALSE, FALSE); + shader_hw_sample(ins, reg1, dst_str, src_str, 0, NULL, NULL); } static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - BOOL has_bumpmat = FALSE; - BOOL has_luminance = FALSE; - BOOL is_color; - int i; - - SHADER_BUFFER *buffer = ins->ctx->buffer; - - char reg_coord[40]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char reg_coord[40], dst_reg[50], src_reg[50]; DWORD reg_dest_code; - /* All versions have a destination register */ + /* All versions have a destination register. The Tx where the texture coordinates come + * from is the varying incarnation of the texture register + */ reg_dest_code = dst->reg.idx; - /* Can directly use the name because texbem is only valid for <= 1.3 shaders */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, reg_coord, &is_color); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_reg); + shader_arb_get_src_param(ins, &ins->src[0], 0, src_reg); + sprintf(reg_coord, "fragment.texcoord[%u]", reg_dest_code); - for(i = 0; i < This->numbumpenvmatconsts; i++) { - if (This->bumpenvmatconst[i].const_num != WINED3D_CONST_NUM_UNUSED - && reg_dest_code == This->bumpenvmatconst[i].texunit) - { - has_bumpmat = TRUE; - break; - } - } - for(i = 0; i < This->numbumpenvmatconsts; i++) { - if (This->luminanceconst[i].const_num != WINED3D_CONST_NUM_UNUSED - && reg_dest_code == This->luminanceconst[i].texunit) - { - has_luminance = TRUE; - break; - } - } - - if(has_bumpmat) { - DWORD src = ins->src[0].reg.idx; - - /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ - - shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code); - shader_addline(buffer, "DP3 TMP.x, TMP2, T%u;\n", src); - shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code); - shader_addline(buffer, "DP3 TMP.y, TMP2, T%u;\n", src); - - /* with projective textures, texbem only divides the static texture coord, not the displacement, - * so we can't let the GL handle this. - */ - if (((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS] - & WINED3DTTFF_PROJECTED) { - shader_addline(buffer, "RCP TMP2.w, %s.w;\n", reg_coord); - shader_addline(buffer, "MUL TMP2.xy, %s, TMP2.w;\n", reg_coord); - shader_addline(buffer, "ADD TMP.xy, TMP, TMP2;\n"); - } else { - shader_addline(buffer, "ADD TMP.xy, TMP, %s;\n", reg_coord); - } - - shader_hw_sample(ins, reg_dest_code, reg_coord, "TMP", FALSE, FALSE); - - if (ins->handler_idx == WINED3DSIH_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); - } + /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed + * The Tx in which the perturbation map is stored is the tempreg incarnation of the texture register + * + * GL_NV_fragment_program_option could handle this in one instruction via X2D: + * X2D TA.xy, fragment.texcoord, T%u, bumpenvmat%u.xzyw + * + * However, the NV extensions are never enabled for <= 2.0 shaders because of the performance penalty that + * comes with it, and texbem is an 1.x only instruction. No 1.x instruction forces us to enable the NV + * extension. + */ + shader_addline(buffer, "SWZ TB, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code); + shader_addline(buffer, "DP3 TA.x, TB, %s;\n", src_reg); + shader_addline(buffer, "SWZ TB, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code); + shader_addline(buffer, "DP3 TA.y, TB, %s;\n", src_reg); + /* with projective textures, texbem only divides the static texture coord, not the displacement, + * so we can't let the GL handle this. + */ + if (((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS] + & WINED3DTTFF_PROJECTED) { + shader_addline(buffer, "RCP TB.w, %s.w;\n", reg_coord); + shader_addline(buffer, "MUL TB.xy, %s, TB.w;\n", reg_coord); + shader_addline(buffer, "ADD TA.xy, TA, TB;\n"); } else { - DWORD tf; - if(reg_dest_code < MAX_TEXTURES) { - tf = ((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; - } else { - tf = 0; - } - /* Without a bump matrix loaded, just sample with the unmodified coordinates */ - shader_hw_sample(ins, reg_dest_code, reg_coord, reg_coord, tf & WINED3DTTFF_PROJECTED, FALSE); + shader_addline(buffer, "ADD TA.xy, TA, %s;\n", reg_coord); + } + + shader_hw_sample(ins, reg_dest_code, dst_reg, "TA", 0, NULL, NULL); + + if (ins->handler_idx == WINED3DSIH_TEXBEML) + { + /* No src swizzles are allowed, so this is ok */ + shader_addline(buffer, "MAD TA, %s.z, luminance%d.x, luminance%d.y;\n", + src_reg, reg_dest_code, reg_dest_code); + shader_addline(buffer, "MUL %s, %s, TA;\n", dst_reg, dst_reg); } } static void pshader_hw_texm3x2pad(const struct wined3d_shader_instruction *ins) { DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char src0_name[50]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src0_name[50], dst_name[50]; + BOOL is_color; + struct wined3d_shader_register tmp_reg = ins->dst[0].reg; shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", reg, src0_name); + /* The next instruction will be a texm3x2tex or texm3x2depth that writes to the uninitialized + * T register. Use this register to store the calculated vector + */ + tmp_reg.idx = reg + 1; + shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color); + shader_addline(buffer, "DP3 %s.x, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name); } static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins) @@ -1259,27 +1950,42 @@ static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins) IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD flags; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_str[8]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char dst_str[50]; char src0_name[50]; + char dst_reg[50]; + BOOL is_color; - sprintf(dst_str, "T%u", reg); + /* We know that we're writing to the uninitialized T register, so use it for temporary storage */ + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color); + + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", reg, src0_name); + shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); } static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; - char src0_name[50]; + char src0_name[50], dst_name[50]; + struct wined3d_shader_register tmp_reg = ins->dst[0].reg; + BOOL is_color; + + /* There are always 2 texm3x3pad instructions followed by one texm3x3[tex,vspec, ...] instruction, with + * incrementing ins->dst[0].register_idx numbers. So the pad instruction already knows the final destination + * register, and this register is uninitialized(otherwise the assembler complains that it is 'redeclared') + */ + tmp_reg.idx = reg + 2 - current_state->current_row; + shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 TMP.%c, T%u, %s;\n", 'x' + current_state->current_row, reg, src0_name); + shader_addline(buffer, "DP3 %s.%c, fragment.texcoord[%u], %s;\n", + dst_name, 'x' + current_state->current_row, reg, src0_name); current_state->texcoord_w[current_state->current_row++] = reg; } @@ -1289,18 +1995,20 @@ static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins) IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD flags; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; - char dst_str[8]; - char src0_name[50]; + char dst_str[50]; + char src0_name[50], dst_name[50]; + BOOL is_color; + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); + shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name); /* Sample the texture using the calculated coordinates */ - sprintf(dst_str, "T%u", reg); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_name, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } @@ -1310,33 +2018,39 @@ static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD flags; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; - char dst_str[8]; + char dst_str[50]; char src0_name[50]; + char dst_reg[50]; + BOOL is_color; + /* Get the dst reg without writemask strings. We know this register is uninitialized, so we can use all + * components for temporary data storage + */ + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); + shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name); /* Construct the eye-ray vector from w coordinates */ - shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%u].w;\n", current_state->texcoord_w[0]); - shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%u].w;\n", current_state->texcoord_w[1]); - shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%u].w;\n", reg); + shader_addline(buffer, "MOV TB.x, fragment.texcoord[%u].w;\n", current_state->texcoord_w[0]); + shader_addline(buffer, "MOV TB.y, fragment.texcoord[%u].w;\n", current_state->texcoord_w[1]); + shader_addline(buffer, "MOV TB.z, fragment.texcoord[%u].w;\n", reg); /* Calculate reflection vector */ - shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n"); - /* The .w is ignored when sampling, so I can use TMP2.w to calculate dot(N, N) */ - shader_addline(buffer, "DP3 TMP2.w, TMP, TMP;\n"); - shader_addline(buffer, "RCP TMP2.w, TMP2.w;\n"); - shader_addline(buffer, "MUL TMP.w, TMP.w, TMP2.w;\n"); - shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n"); - shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n"); + shader_addline(buffer, "DP3 %s.w, %s, TB;\n", dst_reg, dst_reg); + /* The .w is ignored when sampling, so I can use TB.w to calculate dot(N, N) */ + shader_addline(buffer, "DP3 TB.w, %s, %s;\n", dst_reg, dst_reg); + shader_addline(buffer, "RCP TB.w, TB.w;\n"); + shader_addline(buffer, "MUL %s.w, %s.w, TB.w;\n", dst_reg, dst_reg); + shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg); + shader_addline(buffer, "MAD %s, coefmul.x, %s, -TB;\n", dst_reg, dst_reg); /* Sample the texture using the calculated coordinates */ - sprintf(dst_str, "T%u", reg); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } @@ -1347,51 +2061,53 @@ static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins) DWORD flags; DWORD reg = ins->dst[0].reg.idx; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_str[8]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char dst_str[50]; char src0_name[50]; char src1_name[50]; + char dst_reg[50]; + BOOL is_color; shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); shader_arb_get_src_param(ins, &ins->src[0], 1, src1_name); - shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name); + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color); + /* Note: dst_reg.xy is input here, generated by two texm3x3pad instructions */ + shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name); /* Calculate reflection vector. * - * dot(N, E) - * TMP.xyz = 2 * --------- * N - E - * dot(N, N) + * dot(N, E) + * dst_reg.xyz = 2 * --------- * N - E + * dot(N, N) * * Which normalizes the normal vector */ - shader_addline(buffer, "DP3 TMP.w, TMP, %s;\n", src1_name); - shader_addline(buffer, "DP3 TMP2.w, TMP, TMP;\n"); - shader_addline(buffer, "RCP TMP2.w, TMP2.w;\n"); - shader_addline(buffer, "MUL TMP.w, TMP.w, TMP2.w;\n"); - shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n"); - shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -%s;\n", src1_name); + shader_addline(buffer, "DP3 %s.w, %s, %s;\n", dst_reg, dst_reg, src1_name); + shader_addline(buffer, "DP3 TC.w, %s, %s;\n", dst_reg, dst_reg); + shader_addline(buffer, "RCP TC.w, TC.w;\n"); + shader_addline(buffer, "MUL %s.w, %s.w, TC.w;\n", dst_reg, dst_reg); + shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg); + shader_addline(buffer, "MAD %s, coefmul.x, %s, -%s;\n", dst_reg, dst_reg, src1_name); /* Sample the texture using the calculated coordinates */ - sprintf(dst_str, "T%u", reg); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; - BOOL is_color; /* texdepth has an implicit destination, the fragment depth value. It's only parameter, * which is essentially an input, is the destination register because it is the first * parameter. According to the msdn, this must be register r5, but let's keep it more flexible - * here + * here(writemasks/swizzles are not valid on texdepth) */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); + shader_arb_get_dst_param(ins, 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 @@ -1403,9 +2119,9 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) * result. But if r = 0.0, then 0 * inf = 0, which is incorrect. */ shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name); - shader_addline(buffer, "MUL TMP.x, %s.x, %s.y;\n", dst_name, dst_name); - shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n"); - shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n"); + shader_addline(buffer, "MUL TA.x, %s.x, %s.y;\n", dst_name, dst_name); + shader_addline(buffer, "MIN TA.x, TA.x, one.x;\n"); + shader_addline(buffer, "MAX result.depth, TA.x, 0.0;\n"); } /** Process the WINED3DSIO_TEXDP3TEX instruction in ARB: @@ -1413,17 +2129,17 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins) * then perform a 1D texture lookup from stage dstregnum, place into dst. */ static void pshader_hw_texdp3tex(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; DWORD sampler_idx = ins->dst[0].reg.idx; char src0[50]; - char dst_str[8]; + char dst_str[50]; shader_arb_get_src_param(ins, &ins->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); + shader_addline(buffer, "MOV TB, 0.0;\n"); + shader_addline(buffer, "DP3 TB.x, fragment.texcoord[%u], %s;\n", sampler_idx, src0); - sprintf(dst_str, "T%u", sampler_idx); - shader_hw_sample(ins, sampler_idx, dst_str, "TMP", FALSE /* Only one coord, can't be projected */, FALSE); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); + shader_hw_sample(ins, sampler_idx, dst_str, "TB", 0 /* Only one coord, can't be projected */, NULL, NULL); } /** Process the WINED3DSIO_TEXDP3 instruction in ARB: @@ -1433,19 +2149,12 @@ static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins) const struct wined3d_shader_dst_param *dst = &ins->dst[0]; char src0[50]; char dst_str[50]; - char dst_mask[6]; - SHADER_BUFFER *buffer = ins->ctx->buffer; - BOOL is_color; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; /* Handle output register */ - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_str, &is_color); - shader_arb_get_write_mask(ins, dst, dst_mask); - + shader_arb_get_dst_param(ins, dst, dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src0); - shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dst->reg.idx, src0); - - /* TODO: Handle output modifiers */ + shader_addline(buffer, "DP3 %s, fragment.texcoord[%u], %s;\n", dst_str, dst->reg.idx, src0); } /** Process the WINED3DSIO_TEXM3X3 instruction in ARB @@ -1453,21 +2162,16 @@ static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins) static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; - char dst_str[50]; - char dst_mask[6]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char dst_str[50], dst_name[50]; char src0[50]; BOOL is_color; - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_str, &is_color); - shader_arb_get_write_mask(ins, dst, dst_mask); - + shader_arb_get_dst_param(ins, dst, dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src0); - shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst->reg.idx, src0); - shader_addline(buffer, "MOV %s%s, TMP;\n", dst_str, dst_mask); - - /* TODO: Handle output modifiers */ + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color); + shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx, src0); + shader_addline(buffer, "MOV %s, %s;\n", dst_str, dst_name); } /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in ARB: @@ -1477,21 +2181,23 @@ static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins) */ static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; - DWORD dst_reg = ins->dst[0].reg.idx; - char src0[50]; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + const struct wined3d_shader_dst_param *dst = &ins->dst[0]; + char src0[50], dst_name[50]; + BOOL is_color; shader_arb_get_src_param(ins, &ins->src[0], 0, src0); - shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", dst_reg, src0); + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color); + shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx, src0); /* How to deal with the special case dst_name.g == 0? if r != 0, then * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct * result. But if r = 0.0, then 0 * inf = 0, which is incorrect. */ - shader_addline(buffer, "RCP TMP.y, TMP.y;\n"); - shader_addline(buffer, "MUL TMP.x, TMP.x, TMP.y;\n"); - shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n"); - shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n"); + shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name); + shader_addline(buffer, "MUL %s.x, %s.x, %s.y;\n", dst_name, dst_name, dst_name); + shader_addline(buffer, "MIN %s.x, %s.x, one.x;\n", dst_name, dst_name); + shader_addline(buffer, "MAX result.depth, %s.x, 0.0;\n", dst_name); } /** Handles transforming all WINED3DSIO_M?x? opcodes for @@ -1550,26 +2256,25 @@ static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins) } } -static void shader_hw_rsq_rcp(const struct wined3d_shader_instruction *ins) +static void shader_hw_scalar_op(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; - const char *instruction, *sat; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + const char *instruction; char dst[50]; char src[50]; switch(ins->handler_idx) { - case WINED3DSIH_RSQ: instruction = "RSQ"; break; - case WINED3DSIH_RCP: instruction = "RCP"; break; + case WINED3DSIH_RSQ: instruction = "RSQ"; break; + case WINED3DSIH_RCP: instruction = "RCP"; break; + case WINED3DSIH_EXP: instruction = "EX2"; break; + case WINED3DSIH_EXPP: instruction = "EXP"; break; default: instruction = ""; FIXME("Unhandled opcode %#x\n", ins->handler_idx); break; } - if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) sat = "_SAT"; - else sat = ""; - shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */ shader_arb_get_src_param(ins, &ins->src[0], 0, src); if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE) @@ -1580,29 +2285,54 @@ static void shader_hw_rsq_rcp(const struct wined3d_shader_instruction *ins) strcat(src, ".w"); } - shader_addline(buffer, "%s%s %s, %s;\n", instruction, sat, dst, src); + shader_addline(buffer, "%s%s %s, %s;\n", instruction, shader_arb_get_modifier(ins), dst, src); } static void shader_hw_nrm(const struct wined3d_shader_instruction *ins) { - const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[50]; - char dst_wmask[20]; - BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE; - BOOL is_color; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type); - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); + shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); + shader_arb_get_src_param(ins, &ins->src[0], 1 /* Use TB */, src_name); - shader_arb_get_src_param(ins, &ins->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*/ - shader_addline(buffer, "MUL%s %s%s, %s, TMP;\n", sat ? "_SAT" : "", dst_name, dst_wmask, - src_name); + if(pshader && priv->target_version >= NV3) + { + shader_addline(buffer, "NRM%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name); + } + else + { + shader_addline(buffer, "DP3 TA, %s, %s;\n", src_name, src_name); + shader_addline(buffer, "RSQ TA, TA.x;\n"); + /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/ + shader_addline(buffer, "MUL%s %s, %s, TA;\n", shader_arb_get_modifier(ins), dst_name, + src_name); + } +} + +static void shader_hw_lrp(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char dst_name[50]; + char src_name[3][50]; + + /* ARB_fragment_program has a convenient LRP instruction */ + if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { + shader_hw_map2gl(ins); + return; + } + + shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); + shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); + + shader_addline(buffer, "SUB TA, %s, %s;\n", src_name[1], src_name[2]); + shader_addline(buffer, "MAD%s %s, %s, TA, %s;\n", shader_arb_get_modifier(ins), + dst_name, src_name[0], src_name[2]); } static void shader_hw_sincos(const struct wined3d_shader_instruction *ins) @@ -1611,24 +2341,657 @@ static void shader_hw_sincos(const struct wined3d_shader_instruction *ins) * must contain fixed constants. So we need a separate function to filter those constants and * can't use map2gl */ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; const struct wined3d_shader_dst_param *dst = &ins->dst[0]; - SHADER_BUFFER *buffer = ins->ctx->buffer; char dst_name[50]; - char src_name[50]; - char dst_wmask[20]; - BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE; + char src_name0[50], src_name1[50], src_name2[50]; BOOL is_color; - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst, dst_wmask); + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); + if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { + shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); + /* No modifiers are supported on SCS */ + shader_addline(buffer, "SCS %s, %s;\n", dst_name, src_name0); - shader_arb_get_src_param(ins, &ins->src[0], 0, src_name); - shader_addline(buffer, "SCS%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, - src_name); + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name0, &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name0); + } + } else if(priv->target_version >= NV2) { + shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color); + + /* Sincos writemask must be .x, .y or .xy */ + if(dst->write_mask & WINED3DSP_WRITEMASK_0) + shader_addline(buffer, "COS%s %s.x, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0); + if(dst->write_mask & WINED3DSP_WRITEMASK_1) + shader_addline(buffer, "SIN%s %s.y, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0); + } else { + /* Approximate sine and cosine with a taylor series, as per math textbook. The application passes 8 + * helper constants(D3DSINCOSCONST1 and D3DSINCOSCONST2) in src1 and src2. + * + * sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ... + * cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ... + * + * The constants we get are: + * + * +1 +1, -1 -1 +1 +1 -1 -1 + * ---- , ---- , ---- , ----- , ----- , ----- , ------ + * 1!*2 2!*4 3!*8 4!*16 5!*32 6!*64 7!*128 + * + * If used with x^2, x^3, x^4 etc they calculate sin(x/2) and cos(x/2): + * + * (x/2)^2 = x^2 / 4 + * (x/2)^3 = x^3 / 8 + * (x/2)^4 = x^4 / 16 + * (x/2)^5 = x^5 / 32 + * etc + * + * To get the final result: + * sin(x) = 2 * sin(x/2) * cos(x/2) + * cos(x) = cos(x/2)^2 - sin(x/2)^2 + * (from sin(x+y) and cos(x+y) rules) + * + * As per MSDN, dst.z is undefined after the operation, and so is + * dst.x and dst.y if they're masked out by the writemask. Ie + * sincos dst.y, src1, c0, c1 + * returns the sine in dst.y. dst.x and dst.z are undefined, dst.w is not touched. The assembler + * vsa.exe also stops with an error if the dest register is the same register as the source + * register. This means we can use dest.xyz as temporary storage. The assembler vsa.exe output also + * indicates that sincos consumes 8 instruction slots in vs_2_0(and, strangely, in vs_3_0). + */ + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1); + shader_arb_get_src_param(ins, &ins->src[2], 2, src_name2); + shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color); + + shader_addline(buffer, "MUL %s.x, %s, %s;\n", dst_name, src_name0, src_name0); /* x ^ 2 */ + shader_addline(buffer, "MUL TA.y, %s.x, %s;\n", dst_name, src_name0); /* x ^ 3 */ + shader_addline(buffer, "MUL %s.y, TA.y, %s;\n", dst_name, src_name0); /* x ^ 4 */ + shader_addline(buffer, "MUL TA.z, %s.y, %s;\n", dst_name, src_name0); /* x ^ 5 */ + shader_addline(buffer, "MUL %s.z, TA.z, %s;\n", dst_name, src_name0); /* x ^ 6 */ + shader_addline(buffer, "MUL TA.w, %s.z, %s;\n", dst_name, src_name0); /* x ^ 7 */ + + /* sin(x/2) + * + * Unfortunately we don't get the constants in a DP4-capable form. Is there a way to + * properly merge that with MULs in the code above? + * The swizzles .yz and xw however fit into the .yzxw swizzle added to ps_2_0. Maybe + * we can merge the sine and cosine MAD rows to calculate them together. + */ + shader_addline(buffer, "MUL TA.x, %s, %s.w;\n", src_name0, src_name2); /* x^1, +1/(1!*2) */ + shader_addline(buffer, "MAD TA.x, TA.y, %s.x, TA.x;\n", src_name2); /* -1/(3!*8) */ + shader_addline(buffer, "MAD TA.x, TA.z, %s.w, TA.x;\n", src_name1); /* +1/(5!*32) */ + shader_addline(buffer, "MAD TA.x, TA.w, %s.x, TA.x;\n", src_name1); /* -1/(7!*128) */ + + /* cos(x/2) */ + shader_addline(buffer, "MAD TA.y, %s.x, %s.y, %s.z;\n", dst_name, src_name2, src_name2); /* -1/(2!*4), +1.0 */ + shader_addline(buffer, "MAD TA.y, %s.y, %s.z, TA.y;\n", dst_name, src_name1); /* +1/(4!*16) */ + shader_addline(buffer, "MAD TA.y, %s.z, %s.y, TA.y;\n", dst_name, src_name1); /* -1/(6!*64) */ + + if(dst->write_mask & WINED3DSP_WRITEMASK_0) { + /* cos x */ + shader_addline(buffer, "MUL TA.z, TA.y, TA.y;\n"); + shader_addline(buffer, "MAD %s.x, -TA.x, TA.x, TA.z;\n", dst_name); + } + if(dst->write_mask & WINED3DSP_WRITEMASK_1) { + /* sin x */ + shader_addline(buffer, "MUL %s.y, TA.x, TA.y;\n", dst_name); + shader_addline(buffer, "ADD %s.y, %s.y, %s.y;\n", dst_name, dst_name, dst_name); + } + } } -static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info) +static void shader_hw_sgn(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char dst_name[50]; + char src_name[50]; + struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data; + + /* SGN is only valid in vertex shaders */ + if(ctx->target_version == NV2) { + shader_hw_map2gl(ins); + return; + } + shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name); + + /* If SRC > 0.0, -SRC < SRC = TRUE, otherwise false. + * if SRC < 0.0, SRC < -SRC = TRUE. If neither is true, src = 0.0 + */ + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) { + shader_addline(buffer, "SLT %s, -%s, %s;\n", dst_name, src_name, src_name); + } else { + /* src contains TA? Write to the dest first. This won't overwrite our destination. + * Then use TA, and calculate the final result + * + * Not reading from TA? Store the first result in TA to avoid overwriting the + * destination if src reg = dst reg + */ + if(strstr(src_name, "TA")) + { + shader_addline(buffer, "SLT %s, %s, -%s;\n", dst_name, src_name, src_name); + shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name); + shader_addline(buffer, "ADD %s, %s, -TA;\n", dst_name, dst_name); + } + else + { + shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name); + shader_addline(buffer, "SLT %s, %s, -%s;\n", dst_name, src_name, src_name); + shader_addline(buffer, "ADD %s, TA, -%s;\n", dst_name, dst_name); + } + } +} + +static void shader_hw_dsy(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src[50]; + char dst[50]; + char dst_name[50]; + BOOL is_color; + + shader_arb_get_dst_param(ins, &ins->dst[0], dst); + shader_arb_get_src_param(ins, &ins->src[0], 0, src); + shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color); + + shader_addline(buffer, "DDY %s, %s;\n", dst, src); + shader_addline(buffer, "MUL%s %s, %s, ycorrection.y;\n", shader_arb_get_modifier(ins), dst, dst_name); +} + +static DWORD abs_modifier(DWORD mod, BOOL *need_abs) +{ + *need_abs = FALSE; + + switch(mod) + { + case WINED3DSPSM_NONE: return WINED3DSPSM_ABS; + case WINED3DSPSM_NEG: return WINED3DSPSM_ABS; + case WINED3DSPSM_BIAS: *need_abs = TRUE; return WINED3DSPSM_BIAS; + case WINED3DSPSM_BIASNEG: *need_abs = TRUE; return WINED3DSPSM_BIASNEG; + case WINED3DSPSM_SIGN: *need_abs = TRUE; return WINED3DSPSM_SIGN; + case WINED3DSPSM_SIGNNEG: *need_abs = TRUE; return WINED3DSPSM_SIGNNEG; + case WINED3DSPSM_COMP: *need_abs = TRUE; return WINED3DSPSM_COMP; + case WINED3DSPSM_X2: *need_abs = TRUE; return WINED3DSPSM_X2; + case WINED3DSPSM_X2NEG: *need_abs = TRUE; return WINED3DSPSM_X2NEG; + case WINED3DSPSM_DZ: *need_abs = TRUE; return WINED3DSPSM_DZ; + case WINED3DSPSM_DW: *need_abs = TRUE; return WINED3DSPSM_DW; + case WINED3DSPSM_ABS: return WINED3DSPSM_ABS; + case WINED3DSPSM_ABSNEG: return WINED3DSPSM_ABS; + } + FIXME("Unknown modifier %u\n", mod); + return mod; +} + +static void shader_hw_log_pow(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src0[50], src1[50], dst[50]; + struct wined3d_shader_src_param src0_copy = ins->src[0]; + BOOL need_abs = FALSE; + const char *instr; + BOOL arg2 = FALSE; + + switch(ins->handler_idx) + { + case WINED3DSIH_LOG: instr = "LG2"; break; + case WINED3DSIH_LOGP: instr = "LOG"; break; + case WINED3DSIH_POW: instr = "POW"; arg2 = TRUE; break; + default: + ERR("Unexpected instruction %d\n", ins->handler_idx); + return; + } + + /* LOG, LOGP and POW operate on the absolute value of the input */ + src0_copy.modifiers = abs_modifier(src0_copy.modifiers, &need_abs); + + shader_arb_get_dst_param(ins, &ins->dst[0], dst); + shader_arb_get_src_param(ins, &src0_copy, 0, src0); + if(arg2) shader_arb_get_src_param(ins, &ins->src[1], 1, src1); + + if(need_abs) + { + shader_addline(buffer, "ABS TA, %s;\n", src0); + if(arg2) + { + shader_addline(buffer, "%s%s %s, TA, %s;\n", instr, shader_arb_get_modifier(ins), dst, src1); + } + else + { + shader_addline(buffer, "%s%s %s, TA;\n", instr, shader_arb_get_modifier(ins), dst); + } + } + else if(arg2) + { + shader_addline(buffer, "%s%s %s, %s, %s;\n", instr, shader_arb_get_modifier(ins), dst, src0, src1); + } + else + { + shader_addline(buffer, "%s%s %s, %s;\n", instr, shader_arb_get_modifier(ins), dst, src0); + } +} + +static void shader_hw_loop(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src_name[50]; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + /* src0 is aL */ + shader_arb_get_src_param(ins, &ins->src[1], 0, src_name); + + if(vshader) + { + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + + if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n"); + /* The constant loader makes sure to load -1 into iX.w */ + shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name); + shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->loop_no); + shader_addline(buffer, "loop_%u_start:\n", control_frame->loop_no); + } + else + { + shader_addline(buffer, "LOOP %s;\n", src_name); + } +} + +static void shader_hw_rep(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + char src_name[50]; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name); + + /* The constant loader makes sure to load -1 into iX.w */ + if(vshader) + { + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + + if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n"); + + shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name); + shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->loop_no); + shader_addline(buffer, "loop_%u_start:\n", control_frame->loop_no); + } + else + { + shader_addline(buffer, "REP %s;\n", src_name); + } +} + +static void shader_hw_endloop(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + + shader_addline(buffer, "ARAC aL.xy, aL;\n"); + shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->loop_no); + shader_addline(buffer, "loop_%u_end:\n", control_frame->loop_no); + + if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n"); + } + else + { + shader_addline(buffer, "ENDLOOP;\n"); + } +} + +static void shader_hw_endrep(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + + shader_addline(buffer, "ARAC aL.xy, aL;\n"); + shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->loop_no); + shader_addline(buffer, "loop_%u_end:\n", control_frame->loop_no); + + if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n"); + } + else + { + shader_addline(buffer, "ENDREP;\n"); + } +} + +static const struct control_frame *find_last_loop(const struct shader_arb_ctx_priv *priv) +{ + struct control_frame *control_frame; + + LIST_FOR_EACH_ENTRY(control_frame, &priv->control_frames, struct control_frame, entry) + { + if(control_frame->type == LOOP || control_frame->type == REP) return control_frame; + } + ERR("Could not find loop for break\n"); + return NULL; +} + +static void shader_hw_break(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + shader_addline(buffer, "BRA loop_%u_end;\n", control_frame->loop_no); + } + else + { + shader_addline(buffer, "BRK;\n"); + } +} + +static const char *get_compare(COMPARISON_TYPE flags) +{ + switch (flags) + { + case COMPARISON_GT: return "GT"; + case COMPARISON_EQ: return "EQ"; + case COMPARISON_GE: return "GE"; + case COMPARISON_LT: return "LT"; + case COMPARISON_NE: return "NE"; + case COMPARISON_LE: return "LE"; + default: + FIXME("Unrecognized comparison value: %u\n", flags); + return "(\?\?)"; + } +} + +static COMPARISON_TYPE invert_compare(COMPARISON_TYPE flags) +{ + switch (flags) + { + case COMPARISON_GT: return COMPARISON_LE; + case COMPARISON_EQ: return COMPARISON_NE; + case COMPARISON_GE: return COMPARISON_LT; + case COMPARISON_LT: return COMPARISON_GE; + case COMPARISON_NE: return COMPARISON_EQ; + case COMPARISON_LE: return COMPARISON_GT; + default: + FIXME("Unrecognized comparison value: %u\n", flags); + return -1; + } +} + +static void shader_hw_breakc(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data); + char src_name0[50]; + char src_name1[50]; + const char *comp = get_compare(ins->flags); + + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1); + + if(vshader) + { + /* SUBC CC, src0, src1" works only in pixel shaders, so use TA to throw + * away the subtraction result + */ + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRA loop_%u_end (%s.x);\n", control_frame->loop_no, comp); + } + else + { + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRK (%s.x);\n", comp); + } +} + +static void shader_hw_ifc(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + const char *comp; + char src_name0[50]; + char src_name1[50]; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1); + + if(vshader) + { + /* Invert the flag. We jump to the else label if the condition is NOT true */ + comp = get_compare(invert_compare(ins->flags)); + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRA ifc_%u_else (%s.x);\n", control_frame->ifc_no, comp); + } + else + { + comp = get_compare(ins->flags); + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "IF %s.x;\n", comp); + } +} + +static void shader_hw_else(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + shader_addline(buffer, "BRA ifc_%u_endif;\n", control_frame->ifc_no); + shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no); + control_frame->had_else = TRUE; + } + else + { + shader_addline(buffer, "ELSE;\n"); + } +} + +static void shader_hw_endif(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + if(control_frame->had_else) + { + shader_addline(buffer, "ifc_%u_endif:\n", control_frame->ifc_no); + } + else + { + shader_addline(buffer, "#No else branch. else is endif\n"); + shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no); + } + } + else + { + shader_addline(buffer, "ENDIF;\n"); + } +} + +static void shader_hw_texldd(const struct wined3d_shader_instruction *ins) +{ + DWORD sampler_idx = ins->src[1].reg.idx; + char reg_dest[40]; + char reg_src[3][40]; + DWORD flags = TEX_DERIV; + + shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest); + shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src[0]); + shader_arb_get_src_param(ins, &ins->src[2], 1, reg_src[1]); + shader_arb_get_src_param(ins, &ins->src[3], 2, reg_src[2]); + + if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS; + + shader_hw_sample(ins, sampler_idx, reg_dest, reg_src[0], flags, reg_src[1], reg_src[2]); +} + +static void shader_hw_texldl(const struct wined3d_shader_instruction *ins) +{ + DWORD sampler_idx = ins->src[1].reg.idx; + char reg_dest[40]; + char reg_coord[40]; + DWORD flags = TEX_LOD; + + shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest); + shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord); + + if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS; + + shader_hw_sample(ins, sampler_idx, reg_dest, reg_coord, flags, NULL, NULL); +} + +static void shader_hw_label(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + + priv->in_main_func = FALSE; + /* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled + * subroutine, don't generate a label that will make GL complain + */ + if(priv->target_version == ARB) return; + + shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx); +} + +static void vshader_add_footer(IWineD3DVertexShaderImpl *This, struct wined3d_shader_buffer *buffer, + const struct arb_vs_compile_args *args, struct shader_arb_ctx_priv *priv_ctx) +{ + const shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + unsigned int i; + + /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used + * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), + * the fog frag coord is thrown away. If the fog frag coord is used, but not written by + * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) + */ + if(args->super.fog_src == VS_FOG_Z) { + shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); + } else if (!reg_maps->fog) { + /* posFixup.x is always 1.0, so we can savely use it */ + shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\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 TA, posFixup, TMP_OUT.w;\n"); + shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n"); + shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n"); + + if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2) + { + for(i = 0; i < priv_ctx->vs_clipplanes; i++) + { + shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i); + } + } + else if(args->boolclip.clip_control[0]) + { + unsigned int cur_clip = 0; + char component[4] = {'x', 'y', 'z', 'w'}; + + for(i = 0; i < GL_LIMITS(clipplanes); i++) + { + if(args->boolclip.clip_control[1] & (1 << i)) + { + shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n", + component[cur_clip++], i); + } + } + switch(cur_clip) + { + case 0: + shader_addline(buffer, "MOV TA, -helper_const.w;\n"); + break; + case 1: + shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n"); + break; + case 2: + shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n"); + break; + case 3: + shader_addline(buffer, "MOV TA.w, -helper_const.w;\n"); + break; + } + shader_addline(buffer, "MOV result.texcoord[%u], TA;\n", + args->boolclip.clip_control[0] - 1); + } + + /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c + * and the glsl equivalent + */ + if(need_helper_const(gl_info)) { + shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n"); + } else { + shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n"); + shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n"); + } + + shader_addline(buffer, "MOV result.position, TMP_OUT;\n"); + + priv_ctx->footer_written = TRUE; +} + +static void shader_hw_ret(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *) ins->ctx->shader; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(priv->target_version == ARB) return; + + if(vshader) + { + if(priv->in_main_func) vshader_add_footer((IWineD3DVertexShaderImpl *) shader, buffer, priv->cur_vs_args, priv); + } + + shader_addline(buffer, "RET;\n"); +} + +static void shader_hw_call(const struct wined3d_shader_instruction *ins) +{ + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + shader_addline(buffer, "CAL l%u;\n", ins->src[0].reg.idx); +} + +/* GL locking is done by the caller */ +static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_info) { GLuint program_id = 0; const char *blt_vprogram = @@ -1653,7 +3016,8 @@ static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info) return program_id; } -static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type) +/* GL locking is done by the caller */ +static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) { GLuint program_id = 0; static const char * const blt_fprograms[tex_type_count] = @@ -1702,211 +3066,246 @@ static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, en return program_id; } -static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - struct shader_arb_priv *priv = This->shader_priv; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - - if (useVS) { - struct vs_compile_args compile_args; - - TRACE("Using vertex shader\n"); - find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args); - priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args); - - /* Bind the vertex program */ - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); - checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);"); - - /* 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, 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)"); - } - - if (usePS) { - struct ps_compile_args compile_args; - TRACE("Using pixel shader\n"); - find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args); - priv->current_fprogram_id = find_gl_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, - &compile_args); - - /* Bind the fragment program */ - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); - checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);"); - - if(!priv->use_arbfp_fixed_func) { - /* 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, priv->current_fprogram_id); - } else 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)"); - priv->current_fprogram_id = 0; - } -} - -static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - struct shader_arb_priv *priv = This->shader_priv; - GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type]; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - - if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info); - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id)); - glEnable(GL_VERTEX_PROGRAM_ARB); - - if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram)); - glEnable(GL_FRAGMENT_PROGRAM_ARB); -} - -static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - struct shader_arb_priv *priv = This->shader_priv; - const 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 { - glDisable(GL_FRAGMENT_PROGRAM_ARB); - checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); - } -} - -static void shader_arb_destroy(IWineD3DBaseShader *iface) { - IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface; - const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info; - - if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type)) - { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface; - UINT i; - - ENTER_GL(); - for(i = 0; i < This->num_gl_shaders; i++) { - GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId)); - checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))"); - } - LEAVE_GL(); - HeapFree(GetProcessHeap(), 0, This->gl_shaders); - This->gl_shaders = NULL; - This->num_gl_shaders = 0; - This->shader_array_size = 0; - } else { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface; - UINT i; - - ENTER_GL(); - for(i = 0; i < This->num_gl_shaders; i++) { - GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId)); - checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))"); - } - LEAVE_GL(); - HeapFree(GetProcessHeap(), 0, This->gl_shaders); - This->gl_shaders = NULL; - This->num_gl_shaders = 0; - This->shader_array_size = 0; - } -} - -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; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - struct shader_arb_priv *priv = This->shader_priv; - int i; - - if(priv->depth_blt_vprogram_id) { - GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id)); - } - for (i = 0; i < tex_type_count; ++i) { - if (priv->depth_blt_fprogram_id[i]) { - GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i])); - } - } - - 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) { +static void arbfp_add_sRGB_correction(struct wined3d_shader_buffer *buffer, const char *fragcolor, + const char *tmp1, const char *tmp2, const char *tmp3, const char *tmp4, BOOL condcode) +{ /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ - /* Calculate the > 0.0031308 case */ - shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor); - shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor); - shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor); - shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1); - shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1); - /* Calculate the < case */ - shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor); - /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */ - shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor); - shader_addline(buffer, "SGE %s, srgb_consts1.y, %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); + if(condcode) + { + /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */ + shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor); + /* Calculate the > 0.0031308 case */ + shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor); + shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor); + shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor); + shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts1.w;\n", fragcolor, fragcolor); + shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts2.x;\n", fragcolor, fragcolor); + /* Calculate the < case */ + shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts1.x, %s;\n", fragcolor, fragcolor); + } + else + { + /* Calculate the > 0.0031308 case */ + shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor); + shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor); + shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor); + shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1); + shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1); + /* Calculate the < case */ + shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor); + /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */ + shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor); + shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor); + /* Store the components > 0.0031308 in the destination */ + shader_addline(buffer, "MUL %s.xyz, %s, %s;\n", fragcolor, tmp1, tmp3); + /* Add the components that are < 0.0031308 */ + shader_addline(buffer, "MAD %s.xyz, %s, %s, %s;\n", fragcolor, tmp2, tmp4, fragcolor); + /* Move everything into result.color at once. Nvidia hardware cannot handle partial + * result.color writes(.rgb first, then .a), or handle overwriting already written + * components. The assembler uses a temporary register in this case, which is usually + * not allocated from one of our registers that were used earlier. + */ + } + shader_addline(buffer, "MOV result.color, %s;\n", fragcolor); /* [0.0;1.0] clamping. Not needed, this is done implicitly */ } -static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, - SHADER_BUFFER *buffer, const struct ps_compile_args *args) +static const DWORD *find_loop_control_values(IWineD3DBaseShaderImpl *This, DWORD idx) +{ + const local_constant *constant; + + LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry) + { + if (constant->idx == idx) + { + return constant->value; + } + } + return NULL; +} + +static void init_ps_input(const IWineD3DPixelShaderImpl *This, const struct arb_ps_compile_args *args, + struct shader_arb_ctx_priv *priv) +{ + const char *texcoords[8] = + { + "fragment.texcoord[0]", "fragment.texcoord[1]", "fragment.texcoord[2]", "fragment.texcoord[3]", + "fragment.texcoord[4]", "fragment.texcoord[5]", "fragment.texcoord[6]", "fragment.texcoord[7]" + }; + unsigned int i; + const struct wined3d_shader_signature_element *sig = This->input_signature; + const char *semantic_name; + DWORD semantic_idx; + + switch(args->super.vp_mode) + { + case pretransformed: + case fixedfunction: + /* The pixelshader has to collect the varyings on its own. In any case properly load + * color0 and color1. In the case of pretransformed vertices also load texcoords. Set + * other attribs to 0.0. + * + * For fixedfunction this behavior is correct, according to the tests. For pretransformed + * we'd either need a replacement shader that can load other attribs like BINORMAL, or + * load the texcoord attrib pointers to match the pixel shader signature + */ + for(i = 0; i < MAX_REG_INPUT; i++) + { + semantic_name = sig[i].semantic_name; + semantic_idx = sig[i].semantic_idx; + if(semantic_name == NULL) continue; + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if(semantic_idx == 0) priv->ps_input[i] = "fragment.color.primary"; + else if(semantic_idx == 1) priv->ps_input[i] = "fragment.color.secondary"; + else priv->ps_input[i] = "0.0"; + } + else if(args->super.vp_mode == fixedfunction) + { + priv->ps_input[i] = "0.0"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if(semantic_idx < 8) priv->ps_input[i] = texcoords[semantic_idx]; + else priv->ps_input[i] = "0.0"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + if(semantic_idx == 0) priv->ps_input[i] = "fragment.fogcoord"; + else priv->ps_input[i] = "0.0"; + } + else + { + priv->ps_input[i] = "0.0"; + } + + TRACE("v%u, semantic %s%u is %s\n", i, semantic_name, semantic_idx, priv->ps_input[i]); + } + break; + + case vertexshader: + /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord and v8 and v9 in + * fragment.color + */ + for(i = 0; i < 8; i++) + { + priv->ps_input[i] = texcoords[i]; + } + priv->ps_input[8] = "fragment.color.primary"; + priv->ps_input[9] = "fragment.color.secondary"; + break; + } +} + +/* GL locking is done by the caller */ +static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct wined3d_shader_buffer *buffer, + const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; const shader_reg_maps* reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; - const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; const local_constant *lconst; GLuint retval; - const char *fragcolor; - DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This); + char fragcolor[16]; + DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This), next_local, cur; + struct shader_arb_ctx_priv priv_ctx; + BOOL dcl_tmp = args->super.srgb_correction, dcl_td = FALSE; + BOOL want_nv_prog = FALSE; + struct arb_pshader_private *shader_priv = This->backend_priv; + DWORD map; + + char srgbtmp[4][4]; + unsigned int i, found = 0; + + for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) + { + if (!(map & 1) + || (This->color0_mov && i == This->color0_reg) + || (reg_maps->shader_version.major < 2 && i == 0)) + continue; + + sprintf(srgbtmp[found], "R%u", i); + ++found; + if (found == 4) break; + } + + switch(found) { + case 4: dcl_tmp = FALSE; break; + case 0: + sprintf(srgbtmp[0], "TA"); + sprintf(srgbtmp[1], "TB"); + sprintf(srgbtmp[2], "TC"); + sprintf(srgbtmp[3], "TD"); + dcl_td = TRUE; + break; + case 1: + sprintf(srgbtmp[1], "TA"); + sprintf(srgbtmp[2], "TB"); + sprintf(srgbtmp[3], "TC"); + break; + case 2: + sprintf(srgbtmp[2], "TA"); + sprintf(srgbtmp[3], "TB"); + break; + case 3: + sprintf(srgbtmp[3], "TA"); + break; + } /* Create the hw ARB shader */ + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_ps_args = args; + priv_ctx.compiled_fprog = compiled; + priv_ctx.cur_np2fixup_info = &compiled->np2fixup_info; + init_ps_input(This, args, &priv_ctx); + list_init(&priv_ctx.control_frames); + + /* Avoid enabling NV_fragment_program* if we do not need it. + * + * Enabling GL_NV_fragment_program_option causes the driver to occupy a temporary register, + * and it slows down the shader execution noticeably(about 5%). Usually our instruction emulation + * is faster than what we gain from using higher native instructions. There are some things though + * that cannot be emulated. In that case enable the extensions. + * If the extension is enabled, instruction handlers that support both ways will use it. + * + * Testing shows no performance difference between OPTION NV_fragment_program2 and NV_fragment_program. + * So enable the best we can get. + */ + if(reg_maps->usesdsx || reg_maps->usesdsy || reg_maps->loop_depth > 0 || reg_maps->usestexldd || + reg_maps->usestexldl || reg_maps->usesfacing || reg_maps->usesifc || reg_maps->usescall) + { + want_nv_prog = TRUE; + } + shader_addline(buffer, "!!ARBfp1.0\n"); + if(want_nv_prog && GL_SUPPORT(NV_FRAGMENT_PROGRAM2)) { + shader_addline(buffer, "OPTION NV_fragment_program2;\n"); + priv_ctx.target_version = NV3; + } else if(want_nv_prog && GL_SUPPORT(NV_FRAGMENT_PROGRAM_OPTION)) { + shader_addline(buffer, "OPTION NV_fragment_program;\n"); + priv_ctx.target_version = NV2; + } else { + if(want_nv_prog) + { + /* This is an error - either we're advertising the wrong shader version, or aren't enforcing some + * limits properly + */ + ERR("The shader requires instructions that are not available in plain GL_ARB_fragment_program\n"); + ERR("Try GLSL\n"); + } + priv_ctx.target_version = ARB; + } + + if(This->baseShader.reg_maps.highest_render_target > 0) + { + shader_addline(buffer, "OPTION ARB_draw_buffers;\n"); + } if (reg_maps->shader_version.major < 3) { - switch(args->fog) { + switch(args->super.fog) { case FOG_OFF: break; case FOG_LINEAR: @@ -1921,33 +3320,171 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, } } - shader_addline(buffer, "TEMP TMP;\n"); /* Used in matrix ops */ - shader_addline(buffer, "TEMP TMP2;\n"); /* Used in matrix ops */ + /* For now always declare the temps. At least the Nvidia assembler optimizes completely + * unused temps away(but occupies them for the whole shader if they're used once). Always + * declaring them avoids tricky bookkeeping work + */ 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 */ + if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */ shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n"); shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n"); shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n"); if (reg_maps->shader_version.major < 2) { - fragcolor = "R0"; + strcpy(fragcolor, "R0"); } else { - shader_addline(buffer, "TEMP TMP_COLOR;\n"); - fragcolor = "TMP_COLOR"; + if(args->super.srgb_correction) { + if(This->color0_mov) { + sprintf(fragcolor, "R%u", This->color0_reg); + } else { + shader_addline(buffer, "TEMP TMP_COLOR;\n"); + strcpy(fragcolor, "TMP_COLOR"); + } + } else { + strcpy(fragcolor, "result.color"); + } + } + + if(args->super.srgb_correction) { + shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n", + srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high); + shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n", + srgb_sub_high, 0.0, 0.0, 0.0); } /* Base Declarations */ - shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map); + next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, + lconst_map, NULL, &priv_ctx); + + for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; + + cur = compiled->numbumpenvmatconsts; + compiled->bumpenvmatconst[cur].const_num = WINED3D_CONST_NUM_UNUSED; + compiled->bumpenvmatconst[cur].texunit = i; + compiled->luminanceconst[cur].const_num = WINED3D_CONST_NUM_UNUSED; + compiled->luminanceconst[cur].texunit = i; + + /* We can fit the constants into the constant limit for sure because texbem, texbeml, bem and beml are only supported + * in 1.x shaders, and GL_ARB_fragment_program has a constant limit of 24 constants. So in the worst case we're loading + * 8 shader constants, 8 bump matrices and 8 luminance parameters and are perfectly fine. (No NP2 fixup on bumpmapped + * textures due to conditional NP2 restrictions) + * + * Use local constants to load the bump env parameters, not program.env. This avoids collisions with d3d constants of + * shaders in newer shader models. Since the bump env parameters have to share their space with NP2 fixup constants, + * their location is shader dependent anyway and they cannot be loaded globally. + */ + compiled->bumpenvmatconst[cur].const_num = next_local++; + shader_addline(buffer, "PARAM bumpenvmat%d = program.local[%d];\n", + i, compiled->bumpenvmatconst[cur].const_num); + compiled->numbumpenvmatconsts = cur + 1; + + if (!(reg_maps->luminanceparams & (1 << i))) continue; + + compiled->luminanceconst[cur].const_num = next_local++; + shader_addline(buffer, "PARAM luminance%d = program.local[%d];\n", + i, compiled->luminanceconst[cur].const_num); + } + + for(i = 0; i < MAX_CONST_I; i++) + { + compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED; + if (reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2) + { + const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i); + + if(control_values) + { + shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i, + control_values[0], control_values[1], control_values[2]); + } + else + { + compiled->int_consts[i] = next_local; + compiled->num_int_consts++; + shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++); + } + } + } + + if(reg_maps->vpos || reg_maps->usesdsy) + { + compiled->ycorrection = next_local; + shader_addline(buffer, "PARAM ycorrection = program.local[%u];\n", next_local++); + + if(reg_maps->vpos) + { + shader_addline(buffer, "TEMP vpos;\n"); + /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen). + * ycorrection.y: -1.0(onscreen), 1.0(offscreen) + * ycorrection.z: 1.0 + * ycorrection.w: 0.0 + */ + shader_addline(buffer, "MAD vpos, fragment.position, ycorrection.zyww, ycorrection.wxww;\n"); + shader_addline(buffer, "FLR vpos.xy, vpos;\n"); + } + } + else + { + compiled->ycorrection = WINED3D_CONST_NUM_UNUSED; + } + + /* Load constants to fixup NP2 texcoords if there are still free constants left: + * Constants (texture dimensions) for the NP2 fixup are loaded as local program parameters. This will consume + * at most 8 (MAX_FRAGMENT_SAMPLERS / 2) parameters, which is highly unlikely, since the application had to + * use 16 NP2 textures at the same time. In case that we run out of constants the fixup is simply not + * applied / activated. This will probably result in wrong rendering of the texture, but will save us from + * shader compilation errors and the subsequent errors when drawing with this shader. */ + if (priv_ctx.cur_ps_args->super.np2_fixup) { + + struct arb_ps_np2fixup_info* const fixup = priv_ctx.cur_np2fixup_info; + const WORD map = priv_ctx.cur_ps_args->super.np2_fixup; + const UINT max_lconsts = gl_info->ps_arb_max_local_constants; + + fixup->offset = next_local; + fixup->super.active = 0; + + cur = 0; + for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { + if (!(map & (1 << i))) continue; + + if (fixup->offset + (cur >> 1) < max_lconsts) { + fixup->super.active |= (1 << i); + fixup->super.idx[i] = cur++; + } else { + FIXME("No free constant found to load NP2 fixup data into shader. " + "Sampling from this texture will probably look wrong.\n"); + break; + } + } + + fixup->super.num_consts = (cur + 1) >> 1; + if (fixup->super.num_consts) { + shader_addline(buffer, "PARAM np2fixup[%u] = { program.env[%u..%u] };\n", + fixup->super.num_consts, fixup->offset, fixup->super.num_consts + fixup->offset - 1); + } + + next_local += fixup->super.num_consts; + } + + if (shader_priv->clipplane_emulation != ~0U) + { + shader_addline(buffer, "KIL fragment.texcoord[%u];\n", shader_priv->clipplane_emulation); + } /* Base Shader Body */ - shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function); + shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); - if(args->srgb_correction) { - arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB"); + if(args->super.srgb_correction) { + arbfp_add_sRGB_correction(buffer, fragcolor, srgbtmp[0], srgbtmp[1], srgbtmp[2], srgbtmp[3], + priv_ctx.target_version >= NV2); + } else if(reg_maps->shader_version.major < 2) { + shader_addline(buffer, "MOV result.color, %s;\n", fragcolor); } - shader_addline(buffer, "MOV result.color, %s;\n", fragcolor); shader_addline(buffer, "END\n"); /* TODO: change to resource.glObjectHandle or something like that */ @@ -1982,34 +3519,331 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, return retval; } -static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args) +static int compare_sig(const struct wined3d_shader_signature_element *sig1, const struct wined3d_shader_signature_element *sig2) +{ + unsigned int i; + int ret; + + for(i = 0; i < MAX_REG_INPUT; i++) + { + if(sig1[i].semantic_name == NULL || sig2[i].semantic_name == NULL) + { + /* Compare pointers, not contents. One string is NULL(element does not exist), the other one is not NULL */ + if(sig1[i].semantic_name != sig2[i].semantic_name) return sig1[i].semantic_name < sig2[i].semantic_name ? -1 : 1; + continue; + } + + ret = strcmp(sig1[i].semantic_name, sig2[i].semantic_name); + if(ret != 0) return ret; + if(sig1[i].semantic_idx != sig2[i].semantic_idx) return sig1[i].semantic_idx < sig2[i].semantic_idx ? -1 : 1; + if(sig1[i].sysval_semantic != sig2[i].sysval_semantic) return sig1[i].sysval_semantic < sig2[i].sysval_semantic ? -1 : 1; + if(sig1[i].component_type != sig2[i].component_type) return sig1[i].sysval_semantic < sig2[i].component_type ? -1 : 1; + if(sig1[i].register_idx != sig2[i].register_idx) return sig1[i].register_idx < sig2[i].register_idx ? -1 : 1; + if(sig1[i].mask != sig2->mask) return sig1[i].mask < sig2[i].mask ? -1 : 1; + } + return 0; +} + +static struct wined3d_shader_signature_element *clone_sig(const struct wined3d_shader_signature_element *sig) +{ + struct wined3d_shader_signature_element *new; + int i; + char *name; + + new = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new) * MAX_REG_INPUT); + for(i = 0; i < MAX_REG_INPUT; i++) + { + if(sig[i].semantic_name == NULL) + { + continue; + } + + new[i] = sig[i]; + /* Clone the semantic string */ + name = HeapAlloc(GetProcessHeap(), 0, strlen(sig[i].semantic_name) + 1); + strcpy(name, sig[i].semantic_name); + new[i].semantic_name = name; + } + return new; +} + +static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature_element *sig) +{ + struct wine_rb_entry *entry = wine_rb_get(&priv->signature_tree, sig); + struct ps_signature *found_sig; + + if(entry != NULL) + { + found_sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + TRACE("Found existing signature %u\n", found_sig->idx); + return found_sig->idx; + } + found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sig)); + found_sig->sig = clone_sig(sig); + found_sig->idx = priv->ps_sig_number++; + TRACE("New signature stored and assigned number %u\n", found_sig->idx); + if(wine_rb_put(&priv->signature_tree, sig, &found_sig->entry) == -1) + { + ERR("Failed to insert program entry.\n"); + } + return found_sig->idx; +} + +static void init_output_registers(IWineD3DVertexShaderImpl *shader, DWORD sig_num, struct shader_arb_ctx_priv *priv_ctx, + struct arb_vs_compiled_shader *compiled) +{ + unsigned int i, j; + static const char *texcoords[8] = + { + "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]", + "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]" + }; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) shader->baseShader.device; + const struct wined3d_shader_signature_element *sig; + const char *semantic_name; + DWORD semantic_idx, reg_idx; + + /* Write generic input varyings 0 to 7 to result.texcoord[], varying 8 to result.color.primary + * and varying 9 to result.color.secondary + */ + const char *decl_idx_to_string[MAX_REG_INPUT] = + { + texcoords[0], texcoords[1], texcoords[2], texcoords[3], + texcoords[4], texcoords[5], texcoords[6], texcoords[7], + "result.color.primary", "result.color.secondary" + }; + + if(sig_num == ~0) + { + TRACE("Pixel shader uses builtin varyings\n"); + /* Map builtins to builtins */ + for(i = 0; i < 8; i++) + { + priv_ctx->texcrd_output[i] = texcoords[i]; + } + priv_ctx->color_output[0] = "result.color.primary"; + priv_ctx->color_output[1] = "result.color.secondary"; + priv_ctx->fog_output = "result.fogcoord"; + + /* Map declared regs to builtins. Use "TA" to /dev/null unread output */ + for(i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); i++) + { + semantic_name = shader->output_signature[i].semantic_name; + if(semantic_name == NULL) continue; + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + TRACE("o%u is TMP_OUT\n", i); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "TMP_OUT"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + TRACE("o%u is result.pointsize\n", i); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "result.pointsize"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + TRACE("o%u is result.color.?, idx %u\n", i, shader->output_signature[i].semantic_idx); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "result.color.primary"; + else if(shader->output_signature[i].semantic_idx == 1) priv_ctx->vs_output[i] = "result.color.secondary"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + TRACE("o%u is %s\n", i, texcoords[shader->output_signature[i].semantic_idx]); + if(shader->output_signature[i].semantic_idx >= 8) priv_ctx->vs_output[i] = "TA"; + else priv_ctx->vs_output[i] = texcoords[shader->output_signature[i].semantic_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + TRACE("o%u is result.fogcoord\n", i); + if(shader->output_signature[i].semantic_idx > 0) priv_ctx->vs_output[i] = "TA"; + else priv_ctx->vs_output[i] = "result.fogcoord"; + } + else + { + priv_ctx->vs_output[i] = "TA"; + } + } + return; + } + + /* Instead of searching for the signature in the signature list, read the one from the current pixel shader. + * Its maybe not the shader where the signature came from, but it is the same signature and faster to find + */ + sig = ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->input_signature; + TRACE("Pixel shader uses declared varyings\n"); + + /* Map builtin to declared. /dev/null the results by default to the TA temp reg */ + for(i = 0; i < 8; i++) + { + priv_ctx->texcrd_output[i] = "TA"; + } + priv_ctx->color_output[0] = "TA"; + priv_ctx->color_output[1] = "TA"; + priv_ctx->fog_output = "TA"; + + for(i = 0; i < MAX_REG_INPUT; i++) + { + semantic_name = sig[i].semantic_name; + semantic_idx = sig[i].semantic_idx; + reg_idx = sig[i].register_idx; + if(semantic_name == NULL) continue; + + /* If a declared input register is not written by builtin arguments, don't write to it. + * GL_NV_vertex_program makes sure the input defaults to 0.0, which is correct with D3D + * + * Don't care about POSITION and PSIZE here - this is a builtin vertex shader, position goes + * to TMP_OUT in any case + */ + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if(semantic_idx < 8) priv_ctx->texcrd_output[semantic_idx] = decl_idx_to_string[reg_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if(semantic_idx < 2) priv_ctx->color_output[semantic_idx] = decl_idx_to_string[reg_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + if(semantic_idx == 0) priv_ctx->fog_output = decl_idx_to_string[reg_idx]; + } + else + { + continue; + } + + if(strcmp(decl_idx_to_string[reg_idx], "result.color.primary") == 0 || + strcmp(decl_idx_to_string[reg_idx], "result.color.secondary") == 0) + { + compiled->need_color_unclamp = TRUE; + } + } + + /* Map declared to declared */ + for(i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); i++) + { + /* Write unread output to TA to throw them away */ + priv_ctx->vs_output[i] = "TA"; + semantic_name = shader->output_signature[i].semantic_name; + if(semantic_name == NULL) + { + continue; + } + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION) && + shader->output_signature[i].semantic_idx == 0) + { + priv_ctx->vs_output[i] = "TMP_OUT"; + continue; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE) && + shader->output_signature[i].semantic_idx == 0) + { + priv_ctx->vs_output[i] = "result.pointsize"; + continue; + } + + for(j = 0; j < MAX_REG_INPUT; j++) + { + if(sig[j].semantic_name == NULL) + { + continue; + } + + if(strcmp(sig[j].semantic_name, semantic_name) == 0 && + sig[j].semantic_idx == shader->output_signature[i].semantic_idx) + { + priv_ctx->vs_output[i] = decl_idx_to_string[sig[j].register_idx]; + + if(strcmp(priv_ctx->vs_output[i], "result.color.primary") == 0 || + strcmp(priv_ctx->vs_output[i], "result.color.secondary") == 0) + { + compiled->need_color_unclamp = TRUE; + } + } + } + } +} + +/* GL locking is done by the caller */ +static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, struct wined3d_shader_buffer *buffer, + const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled) { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; const shader_reg_maps *reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; - const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const local_constant *lconst; GLuint ret; - DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This); + DWORD next_local, *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This); + struct shader_arb_ctx_priv priv_ctx; + unsigned int i; + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_vs_args = args; + list_init(&priv_ctx.control_frames); + init_output_registers(This, args->ps_signature, &priv_ctx, compiled); /* 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); + /* Always enable the NV extension if available. Unlike fragment shaders, there is no + * mesurable performance penalty, and we can always make use of it for clipplanes. + */ + if(GL_SUPPORT(NV_VERTEX_PROGRAM3)) { + shader_addline(buffer, "OPTION NV_vertex_program3;\n"); + priv_ctx.target_version = NV3; + shader_addline(buffer, "ADDRESS aL;\n"); + } else if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) { + shader_addline(buffer, "OPTION NV_vertex_program2;\n"); + priv_ctx.target_version = NV2; + shader_addline(buffer, "ADDRESS aL;\n"); + } else { + priv_ctx.target_version = ARB; + } - shader_addline(buffer, "TEMP TMP;\n"); + shader_addline(buffer, "TEMP TMP_OUT;\n"); + if(need_helper_const(gl_info)) { + shader_addline(buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset); + } + if(need_mova_const((IWineD3DBaseShader *) This, gl_info)) { + shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n"); + shader_addline(buffer, "TEMP A0_SHADOW;\n"); + } + + shader_addline(buffer, "TEMP TA;\n"); /* Base Declarations */ - shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map); + next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, + lconst_map, &priv_ctx.vs_clipplanes, &priv_ctx); + + for(i = 0; i < MAX_CONST_I; i++) + { + compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED; + if(reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2) + { + const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i); + + if(control_values) + { + shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i, + control_values[0], control_values[1], control_values[2]); + } + else + { + compiled->int_consts[i] = next_local; + compiled->num_int_consts++; + shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++); + } + } + } /* We need a constant to fixup the final position */ - shader_addline(buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS); + shader_addline(buffer, "PARAM posFixup = program.local[%u];\n", next_local); + compiled->pos_fixup = next_local++; /* 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 @@ -2025,7 +3859,8 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, 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) { + if ((GLINFO_LOCATION).quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !device->frag_pipe->ffp_proj_control) + { int i; for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) { if(This->baseShader.reg_maps.texcoord_mask[i] != 0 && @@ -2036,37 +3871,12 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, } } + /* The shader starts with the main function */ + priv_ctx.in_main_func = TRUE; /* Base Shader Body */ - shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function); + shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); - /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used - * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), - * the fog frag coord is thrown away. If the fog frag coord is used, but not written by - * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) - */ - if(args->fog_src == VS_FOG_Z) { - shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n"); - } else if (!reg_maps->fog) { - shader_addline(buffer, "MOV result.fogcoord, helper_const.w;\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"); + if(!priv_ctx.footer_written) vshader_add_footer(This, buffer, args, &priv_ctx); shader_addline(buffer, "END\n"); @@ -2101,7 +3911,535 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, return ret; } -static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) +/* GL locking is done by the caller */ +static struct arb_ps_compiled_shader *find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct arb_ps_compile_args *args) +{ + UINT i; + DWORD new_size; + struct arb_ps_compiled_shader *new_array; + struct wined3d_shader_buffer buffer; + struct arb_pshader_private *shader_data; + GLuint ret; + + if(!shader->backend_priv) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) shader->baseShader.device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct shader_arb_priv *priv = device->shader_priv; + + shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + shader_data = shader->backend_priv; + shader_data->clamp_consts = shader->baseShader.reg_maps.shader_version.major == 1; + + if(shader->baseShader.reg_maps.shader_version.major < 3) shader_data->input_signature_idx = ~0; + else shader_data->input_signature_idx = find_input_signature(priv, shader->input_signature); + + shader_data->has_signature_idx = TRUE; + TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx); + + if (!device->vs_clipping) + shader_data->clipplane_emulation = shader_find_free_input_register(&shader->baseShader.reg_maps, + GL_LIMITS(texture_stages) - 1); + else + shader_data->clipplane_emulation = ~0U; + } + shader_data = shader->backend_priv; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) { + return &shader_data->gl_shaders[i]; + } + } + + TRACE("No matching GL shader found, compiling a new shader\n"); + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + pixelshader_update_samplers(&shader->baseShader.reg_maps, + ((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures); + + if (!shader_buffer_init(&buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + return 0; + } + + ret = shader_arb_generate_pshader(shader, &buffer, args, + &shader_data->gl_shaders[shader_data->num_gl_shaders]); + shader_buffer_free(&buffer); + shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret; + + return &shader_data->gl_shaders[shader_data->num_gl_shaders++]; +} + +static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const struct arb_vs_compile_args *new, + const DWORD use_map, BOOL skip_int) { + if((stored->super.swizzle_map & use_map) != new->super.swizzle_map) return FALSE; + if(stored->super.fog_src != new->super.fog_src) return FALSE; + if(stored->boolclip_compare != new->boolclip_compare) return FALSE; + if(stored->ps_signature != new->ps_signature) return FALSE; + if(stored->vertex_samplers_compare != new->vertex_samplers_compare) return FALSE; + if(skip_int) return TRUE; + + return memcmp(stored->loop_ctrl, new->loop_ctrl, sizeof(stored->loop_ctrl)) == 0; +} + +static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct arb_vs_compile_args *args) +{ + UINT i; + DWORD new_size; + struct arb_vs_compiled_shader *new_array; + DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; + struct wined3d_shader_buffer buffer; + struct arb_vshader_private *shader_data; + GLuint ret; + const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info; + + if(!shader->backend_priv) { + shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + } + shader_data = shader->backend_priv; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map, GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION))) { + return &shader_data->gl_shaders[i]; + } + } + + TRACE("No matching GL shader found, compiling a new shader\n"); + + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + if (!shader_buffer_init(&buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + return 0; + } + + ret = shader_arb_generate_vshader(shader, &buffer, args, + &shader_data->gl_shaders[shader_data->num_gl_shaders]); + shader_buffer_free(&buffer); + shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret; + + return &shader_data->gl_shaders[shader_data->num_gl_shaders++]; +} + +static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, + struct arb_ps_compile_args *args) +{ + int i; + WORD int_skip; + const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info; + find_ps_compile_args(shader, stateblock, &args->super); + + /* This forces all local boolean constants to 1 to make them stateblock independent */ + args->bools = shader->baseShader.reg_maps.local_bool_consts; + + for(i = 0; i < MAX_CONST_B; i++) + { + if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i); + } + + /* Skip if unused or local, or supported natively */ + int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts; + if(int_skip == 0xffff || GL_SUPPORT(NV_FRAGMENT_PROGRAM_OPTION)) + { + memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl)); + return; + } + + for(i = 0; i < MAX_CONST_I; i++) + { + if(int_skip & (1 << i)) + { + args->loop_ctrl[i][0] = 0; + args->loop_ctrl[i][1] = 0; + args->loop_ctrl[i][2] = 0; + } + else + { + args->loop_ctrl[i][0] = stateblock->pixelShaderConstantI[i * 4]; + args->loop_ctrl[i][1] = stateblock->pixelShaderConstantI[i * 4 + 1]; + args->loop_ctrl[i][2] = stateblock->pixelShaderConstantI[i * 4 + 2]; + } + } +} + +static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, + struct arb_vs_compile_args *args) +{ + int i; + WORD int_skip; + IWineD3DDeviceImpl *dev = (IWineD3DDeviceImpl *)shader->baseShader.device; + const struct wined3d_gl_info *gl_info = &dev->adapter->gl_info; + find_vs_compile_args(shader, stateblock, &args->super); + + args->boolclip_compare = 0; + if(use_ps(stateblock)) + { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) stateblock->pixelShader; + struct arb_pshader_private *shader_priv = ps->backend_priv; + args->ps_signature = shader_priv->input_signature_idx; + + args->boolclip.clip_control[0] = shader_priv->clipplane_emulation + 1; + } + else + { + args->ps_signature = ~0; + if(!dev->vs_clipping) + { + args->boolclip.clip_control[0] = ffp_clip_emul(stateblock) ? GL_LIMITS(texture_stages) : 0; + } + /* Otherwise: Setting boolclip_compare set clip_control[0] to 0 */ + } + + if(args->boolclip.clip_control[0]) + { + if(stateblock->renderState[WINED3DRS_CLIPPING]) + { + args->boolclip.clip_control[1] = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]; + } + /* clip_control[1] was set to 0 by setting boolclip_compare to 0 */ + } + + /* This forces all local boolean constants to 1 to make them stateblock independent */ + args->boolclip.bools = shader->baseShader.reg_maps.local_bool_consts; + /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */ + for(i = 0; i < MAX_CONST_B; i++) + { + if(stateblock->vertexShaderConstantB[i]) args->boolclip.bools |= ( 1 << i); + } + + args->vertex_samplers[0] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0]; + args->vertex_samplers[1] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1]; + args->vertex_samplers[2] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2]; + args->vertex_samplers[3] = 0; + + /* Skip if unused or local */ + int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts; + if(int_skip == 0xffff || GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) /* This is about flow control, not clipping */ + { + memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl)); + return; + } + + for(i = 0; i < MAX_CONST_I; i++) + { + if(int_skip & (1 << i)) + { + args->loop_ctrl[i][0] = 0; + args->loop_ctrl[i][1] = 0; + args->loop_ctrl[i][2] = 0; + } + else + { + args->loop_ctrl[i][0] = stateblock->vertexShaderConstantI[i * 4]; + args->loop_ctrl[i][1] = stateblock->vertexShaderConstantI[i * 4 + 1]; + args->loop_ctrl[i][2] = stateblock->vertexShaderConstantI[i * 4 + 2]; + } + } +} + +/* GL locking is done by the caller */ +static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) +{ + IWineD3DDeviceImpl *This = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + struct shader_arb_priv *priv = This->shader_priv; + const struct wined3d_gl_info *gl_info = context->gl_info; + int i; + + /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */ + if (usePS) { + struct arb_ps_compile_args compile_args; + struct arb_ps_compiled_shader *compiled; + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader; + + TRACE("Using pixel shader %p\n", This->stateBlock->pixelShader); + find_arb_ps_compile_args(ps, This->stateBlock, &compile_args); + compiled = find_arb_pshader(ps, &compile_args); + priv->current_fprogram_id = compiled->prgId; + priv->compiled_fprog = compiled; + + /* Bind the fragment program */ + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);"); + + if(!priv->use_arbfp_fixed_func) { + /* 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, priv->current_fprogram_id); + + /* Pixel Shader 1.x constants are clamped to [-1;1], Pixel Shader 2.0 constants are not. If switching between + * a 1.x and newer shader, reload the first 8 constants + */ + if(priv->last_ps_const_clamped != ((struct arb_pshader_private *) ps->backend_priv)->clamp_consts) + { + priv->last_ps_const_clamped = ((struct arb_pshader_private *) ps->backend_priv)->clamp_consts; + This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, 8); + for(i = 0; i < 8; i++) + { + context->pshader_const_dirty[i] = 1; + } + /* Also takes care of loading local constants */ + shader_arb_load_constants(context, TRUE, FALSE); + } + else + { + shader_arb_ps_local_constants(This); + } + + /* Force constant reloading for the NP2 fixup (see comment in shader_glsl_select for more info) */ + if (compiled->np2fixup_info.super.active) + shader_arb_load_np2fixup_constants((IWineD3DDevice *)This, usePS, useVS); + } else 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)"); + priv->current_fprogram_id = 0; + } + + if (useVS) { + struct arb_vs_compile_args compile_args; + struct arb_vs_compiled_shader *compiled; + IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader; + + TRACE("Using vertex shader %p\n", This->stateBlock->vertexShader); + find_arb_vs_compile_args(vs, This->stateBlock, &compile_args); + compiled = find_arb_vshader(vs, &compile_args); + priv->current_vprogram_id = compiled->prgId; + priv->compiled_vprog = compiled; + + /* Bind the vertex program */ + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); + checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);"); + + /* 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, priv->current_vprogram_id); + shader_arb_vs_local_constants(This); + + if(priv->last_vs_color_unclamp != compiled->need_color_unclamp) { + priv->last_vs_color_unclamp = compiled->need_color_unclamp; + + if (GL_SUPPORT(ARB_COLOR_BUFFER_FLOAT)) { + GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, !compiled->need_color_unclamp)); + checkGLcall("glClampColorARB"); + } else { + FIXME("vertex color clamp needs to be changed, but extension not supported.\n"); + } + } + } else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) { + priv->current_vprogram_id = 0; + glDisable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); + } +} + +/* GL locking is done by the caller */ +static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = This->shader_priv; + GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type]; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + + if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id)); + glEnable(GL_VERTEX_PROGRAM_ARB); + + if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram)); + glEnable(GL_FRAGMENT_PROGRAM_ARB); +} + +/* GL locking is done by the caller */ +static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = This->shader_priv; + const struct 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);"); + + 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);"); + + 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_destroy(IWineD3DBaseShader *iface) { + IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)baseShader->baseShader.device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + + if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type)) + { + IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface; + struct arb_pshader_private *shader_data = This->backend_priv; + UINT i; + + if(!shader_data) return; /* This can happen if a shader was never compiled */ + ENTER_GL(); + + if(shader_data->num_gl_shaders) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + + for(i = 0; i < shader_data->num_gl_shaders; i++) { + GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId)); + checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))"); + } + LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + HeapFree(GetProcessHeap(), 0, shader_data); + This->backend_priv = NULL; + } else { + IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface; + struct arb_vshader_private *shader_data = This->backend_priv; + UINT i; + + if(!shader_data) return; /* This can happen if a shader was never compiled */ + ENTER_GL(); + + if(shader_data->num_gl_shaders) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + + for(i = 0; i < shader_data->num_gl_shaders; i++) { + GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId)); + checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))"); + } + LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + HeapFree(GetProcessHeap(), 0, shader_data); + This->backend_priv = NULL; + } +} + +static int sig_tree_compare(const void *key, const struct wine_rb_entry *entry) +{ + struct ps_signature *e = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + return compare_sig(key, e->sig); +} + +struct wine_rb_functions sig_tree_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + sig_tree_compare +}; + +static HRESULT shader_arb_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv)); + if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1) + { + ERR("RB tree init failed\n"); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; + } + This->shader_priv = priv; + return WINED3D_OK; +} + +static void release_signature(struct wine_rb_entry *entry, void *context) +{ + struct ps_signature *sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + int i; + for(i = 0; i < MAX_REG_INPUT; i++) + { + HeapFree(GetProcessHeap(), 0, (char *) sig->sig[i].semantic_name); + } + HeapFree(GetProcessHeap(), 0, sig->sig); + HeapFree(GetProcessHeap(), 0, sig); +} + +/* Context activation is done by the caller. */ +static void shader_arb_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct shader_arb_priv *priv = This->shader_priv; + int i; + + ENTER_GL(); + if(priv->depth_blt_vprogram_id) { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id)); + } + for (i = 0; i < tex_type_count; ++i) { + if (priv->depth_blt_fprogram_id[i]) { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i])); + } + } + LEAVE_GL(); + + wine_rb_destroy(&priv->signature_tree, release_signature, NULL); + HeapFree(GetProcessHeap(), 0, This->shader_priv); +} + +static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) { + return TRUE; +} + +static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const struct 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 @@ -2109,17 +4447,47 @@ static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *g 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) - ARB_SHADER_RESERVED_VS_CONSTS; + if(GL_SUPPORT(NV_VERTEX_PROGRAM3)) + { + pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); + TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (NV_VERTEX_PROGRAM3)\n"); + } + else if(GL_LIMITS(vshader_constantsF) >= 256) + { + /* Shader Model 2.0 requires at least 256 vertex shader constants */ + pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0); + TRACE_(d3d_caps)("Hardware vertex shader version 2.0 enabled (ARB_PROGRAM)\n"); + } + else + { + 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"); - pCaps->MaxPixelShaderConst = GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS; + if(GL_SUPPORT(NV_FRAGMENT_PROGRAM2)) + { + pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); + TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (NV_FRAGMENT_PROGRAM2)\n"); + } + else if(GL_LIMITS(pshader_constantsF) >= 32) + { + /* Shader Model 2.0 requires at least 32 pixel shader constants */ + pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0); + TRACE_(d3d_caps)("Hardware pixel shader version 2.0 enabled (ARB_PROGRAM)\n"); + } + else + { + pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4); + TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n"); + } + pCaps->PixelShader1xMaxValue = 8.0f; + pCaps->MaxPixelShaderConst = GL_LIMITS(pshader_constantsF); } + + pCaps->VSClipping = use_nv_clip(gl_info); } static BOOL shader_arb_color_fixup_supported(struct color_fixup_desc fixup) @@ -2142,10 +4510,9 @@ static BOOL shader_arb_color_fixup_supported(struct color_fixup_desc fixup) } static void shader_arb_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) { - BOOL saturate; DWORD shift; char write_mask[20], regstr[50]; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; BOOL is_color = FALSE; const struct wined3d_shader_dst_param *dst; @@ -2154,14 +4521,15 @@ static void shader_arb_add_instruction_modifiers(const struct wined3d_shader_ins dst = &ins->dst[0]; shift = dst->shift; if(shift == 0) return; /* Saturate alone is handled by the instructions */ - saturate = dst->modifiers & WINED3DSPDM_SATURATE; shader_arb_get_write_mask(ins, dst, write_mask); - shader_arb_get_register_name(ins->ctx->shader, dst->reg.type, - dst->reg.idx, !!dst->reg.rel_addr, regstr, &is_color); + shader_arb_get_register_name(ins, &dst->reg, regstr, &is_color); - /* Generate a line that does the output modifier computation */ - shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", saturate ? "_SAT" : "", + /* Generate a line that does the output modifier computation + * FIXME: _SAT vs shift? _SAT alone is already handled in the instructions, if this + * maps problems in e.g. _d4_sat modify shader_arb_get_modifier + */ + shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", shader_arb_get_modifier(ins), regstr, write_mask, regstr, shift_tab[shift]); } @@ -2170,10 +4538,10 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_ABS */ shader_hw_map2gl, /* WINED3DSIH_ADD */ shader_hw_map2gl, /* WINED3DSIH_BEM */ pshader_hw_bem, - /* WINED3DSIH_BREAK */ NULL, - /* WINED3DSIH_BREAKC */ NULL, + /* WINED3DSIH_BREAK */ shader_hw_break, + /* WINED3DSIH_BREAKC */ shader_hw_breakc, /* WINED3DSIH_BREAKP */ NULL, - /* WINED3DSIH_CALL */ NULL, + /* WINED3DSIH_CALL */ shader_hw_call, /* WINED3DSIH_CALLNZ */ NULL, /* WINED3DSIH_CMP */ pshader_hw_cmp, /* WINED3DSIH_CND */ pshader_hw_cnd, @@ -2186,23 +4554,23 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_DP3 */ shader_hw_map2gl, /* WINED3DSIH_DP4 */ shader_hw_map2gl, /* WINED3DSIH_DST */ shader_hw_map2gl, - /* WINED3DSIH_DSX */ NULL, - /* WINED3DSIH_DSY */ NULL, - /* WINED3DSIH_ELSE */ NULL, - /* WINED3DSIH_ENDIF */ NULL, - /* WINED3DSIH_ENDLOOP */ NULL, - /* WINED3DSIH_ENDREP */ NULL, - /* WINED3DSIH_EXP */ shader_hw_map2gl, - /* WINED3DSIH_EXPP */ shader_hw_map2gl, + /* WINED3DSIH_DSX */ shader_hw_map2gl, + /* WINED3DSIH_DSY */ shader_hw_dsy, + /* WINED3DSIH_ELSE */ shader_hw_else, + /* WINED3DSIH_ENDIF */ shader_hw_endif, + /* WINED3DSIH_ENDLOOP */ shader_hw_endloop, + /* WINED3DSIH_ENDREP */ shader_hw_endrep, + /* WINED3DSIH_EXP */ shader_hw_scalar_op, + /* WINED3DSIH_EXPP */ shader_hw_scalar_op, /* WINED3DSIH_FRC */ shader_hw_map2gl, - /* WINED3DSIH_IF */ NULL, - /* WINED3DSIH_IFC */ NULL, - /* WINED3DSIH_LABEL */ NULL, + /* WINED3DSIH_IF */ NULL /* Hardcoded into the shader */, + /* WINED3DSIH_IFC */ shader_hw_ifc, + /* WINED3DSIH_LABEL */ shader_hw_label, /* WINED3DSIH_LIT */ shader_hw_map2gl, - /* WINED3DSIH_LOG */ shader_hw_map2gl, - /* WINED3DSIH_LOGP */ shader_hw_map2gl, - /* WINED3DSIH_LOOP */ NULL, - /* WINED3DSIH_LRP */ shader_hw_map2gl, + /* WINED3DSIH_LOG */ shader_hw_log_pow, + /* WINED3DSIH_LOGP */ shader_hw_log_pow, + /* WINED3DSIH_LOOP */ shader_hw_loop, + /* WINED3DSIH_LRP */ shader_hw_lrp, /* WINED3DSIH_M3x2 */ shader_hw_mnxn, /* WINED3DSIH_M3x3 */ shader_hw_mnxn, /* WINED3DSIH_M3x4 */ shader_hw_mnxn, @@ -2217,14 +4585,14 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_NOP */ shader_hw_nop, /* WINED3DSIH_NRM */ shader_hw_nrm, /* WINED3DSIH_PHASE */ NULL, - /* WINED3DSIH_POW */ shader_hw_map2gl, - /* WINED3DSIH_RCP */ shader_hw_rsq_rcp, - /* WINED3DSIH_REP */ NULL, - /* WINED3DSIH_RET */ NULL, - /* WINED3DSIH_RSQ */ shader_hw_rsq_rcp, + /* WINED3DSIH_POW */ shader_hw_log_pow, + /* WINED3DSIH_RCP */ shader_hw_scalar_op, + /* WINED3DSIH_REP */ shader_hw_rep, + /* WINED3DSIH_RET */ shader_hw_ret, + /* WINED3DSIH_RSQ */ shader_hw_scalar_op, /* WINED3DSIH_SETP */ NULL, /* WINED3DSIH_SGE */ shader_hw_map2gl, - /* WINED3DSIH_SGN */ NULL, + /* WINED3DSIH_SGN */ shader_hw_sgn, /* WINED3DSIH_SINCOS */ shader_hw_sincos, /* WINED3DSIH_SLT */ shader_hw_map2gl, /* WINED3DSIH_SUB */ shader_hw_map2gl, @@ -2236,8 +4604,8 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_TEXDP3 */ pshader_hw_texdp3, /* WINED3DSIH_TEXDP3TEX */ pshader_hw_texdp3tex, /* WINED3DSIH_TEXKILL */ pshader_hw_texkill, - /* WINED3DSIH_TEXLDD */ NULL, - /* WINED3DSIH_TEXLDL */ NULL, + /* WINED3DSIH_TEXLDD */ shader_hw_texldd, + /* WINED3DSIH_TEXLDL */ shader_hw_texldl, /* WINED3DSIH_TEXM3x2DEPTH */ pshader_hw_texm3x2depth, /* WINED3DSIH_TEXM3x2PAD */ pshader_hw_texm3x2pad, /* WINED3DSIH_TEXM3x2TEX */ pshader_hw_texm3x2tex, @@ -2252,8 +4620,391 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_TEXREG2RGB */ pshader_hw_texreg2rgb, }; +static inline BOOL get_bool_const(const struct wined3d_shader_instruction *ins, IWineD3DBaseShaderImpl *This, DWORD idx) +{ + BOOL vshader = shader_is_vshader_version(This->baseShader.reg_maps.shader_version.type); + WORD bools = 0; + WORD flag = (1 << idx); + const local_constant *constant; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + + if(This->baseShader.reg_maps.local_bool_consts & flag) + { + /* What good is a if(bool) with a hardcoded local constant? I don't know, but handle it */ + LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsB, local_constant, entry) + { + if (constant->idx == idx) + { + return constant->value[0]; + } + } + ERR("Local constant not found\n"); + return FALSE; + } + else + { + if(vshader) bools = priv->cur_vs_args->boolclip.bools; + else bools = priv->cur_ps_args->bools; + return bools & flag; + } +} + +static void get_loop_control_const(const struct wined3d_shader_instruction *ins, + IWineD3DBaseShaderImpl *This, UINT idx, struct wined3d_shader_loop_control *loop_control) +{ + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + + /* Integer constants can either be a local constant, or they can be stored in the shader + * type specific compile args. */ + if (This->baseShader.reg_maps.local_int_consts & (1 << idx)) + { + const local_constant *constant; + + LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry) + { + if (constant->idx == idx) + { + loop_control->count = constant->value[0]; + loop_control->start = constant->value[1]; + /* Step is signed. */ + loop_control->step = (int)constant->value[2]; + return; + } + } + /* If this happens the flag was set incorrectly */ + ERR("Local constant not found\n"); + loop_control->count = 0; + loop_control->start = 0; + loop_control->step = 0; + return; + } + + switch (This->baseShader.reg_maps.shader_version.type) + { + case WINED3D_SHADER_TYPE_VERTEX: + /* Count and aL start value are unsigned */ + loop_control->count = priv->cur_vs_args->loop_ctrl[idx][0]; + loop_control->start = priv->cur_vs_args->loop_ctrl[idx][1]; + /* Step is signed. */ + loop_control->step = ((char)priv->cur_vs_args->loop_ctrl[idx][2]); + break; + + case WINED3D_SHADER_TYPE_PIXEL: + loop_control->count = priv->cur_ps_args->loop_ctrl[idx][0]; + loop_control->start = priv->cur_ps_args->loop_ctrl[idx][1]; + loop_control->step = ((char)priv->cur_ps_args->loop_ctrl[idx][2]); + break; + + default: + FIXME("Unhandled shader type %#x.\n", This->baseShader.reg_maps.shader_version.type); + break; + } +} + +static void record_instruction(struct list *list, const struct wined3d_shader_instruction *ins) +{ + unsigned int i; + struct wined3d_shader_dst_param *dst_param = NULL; + struct wined3d_shader_src_param *src_param = NULL, *rel_addr = NULL; + struct recorded_instruction *rec = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rec)); + if(!rec) + { + ERR("Out of memory\n"); + return; + } + + rec->ins = *ins; + dst_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param)); + if(!dst_param) goto free; + *dst_param = *ins->dst; + if(ins->dst->reg.rel_addr) + { + rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param->reg.rel_addr)); + if(!rel_addr) goto free; + *rel_addr = *ins->dst->reg.rel_addr; + dst_param->reg.rel_addr = rel_addr; + } + rec->ins.dst = dst_param; + + src_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*src_param) * ins->src_count); + if(!src_param) goto free; + for(i = 0; i < ins->src_count; i++) + { + src_param[i] = ins->src[i]; + if(ins->src[i].reg.rel_addr) + { + rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*rel_addr)); + if(!rel_addr) goto free; + *rel_addr = *ins->src[i].reg.rel_addr; + src_param[i].reg.rel_addr = rel_addr; + } + } + rec->ins.src = src_param; + list_add_tail(list, &rec->entry); + return; + +free: + ERR("Out of memory\n"); + if(dst_param) + { + HeapFree(GetProcessHeap(), 0, (void *) dst_param->reg.rel_addr); + HeapFree(GetProcessHeap(), 0, dst_param); + } + if(src_param) + { + for(i = 0; i < ins->src_count; i++) + { + HeapFree(GetProcessHeap(), 0, (void *) src_param[i].reg.rel_addr); + } + HeapFree(GetProcessHeap(), 0, src_param); + } + HeapFree(GetProcessHeap(), 0, rec); +} + +static void free_recorded_instruction(struct list *list) +{ + struct recorded_instruction *rec_ins, *entry2; + unsigned int i; + + LIST_FOR_EACH_ENTRY_SAFE(rec_ins, entry2, list, struct recorded_instruction, entry) + { + list_remove(&rec_ins->entry); + if(rec_ins->ins.dst) + { + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst->reg.rel_addr); + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst); + } + if(rec_ins->ins.src) + { + for(i = 0; i < rec_ins->ins.src_count; i++) + { + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src[i].reg.rel_addr); + } + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src); + } + HeapFree(GetProcessHeap(), 0, rec_ins); + } +} + +static void shader_arb_handle_instruction(const struct wined3d_shader_instruction *ins) { + SHADER_HANDLER hw_fct; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; + struct control_frame *control_frame; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; + BOOL bool_const; + + if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP) + { + control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); + list_add_head(&priv->control_frames, &control_frame->entry); + + if(ins->handler_idx == WINED3DSIH_LOOP) control_frame->type = LOOP; + if(ins->handler_idx == WINED3DSIH_REP) control_frame->type = REP; + + if(priv->target_version >= NV2) + { + control_frame->loop_no = priv->num_loops++; + priv->loop_depth++; + } + else + { + /* Don't bother recording when we're in a not used if branch */ + if(priv->muted) + { + return; + } + + if(!priv->recording) + { + list_init(&priv->record); + priv->recording = TRUE; + control_frame->outer_loop = TRUE; + get_loop_control_const(ins, This, ins->src[0].reg.idx, &control_frame->loop_control); + return; /* Instruction is handled */ + } + /* Record this loop in the outer loop's recording */ + } + } + else if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP) + { + if(priv->target_version >= NV2) + { + /* Nothing to do. The control frame is popped after the HW instr handler */ + } + else + { + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + list_remove(&control_frame->entry); + + if(control_frame->outer_loop) + { + int iteration, aL = 0; + struct list copy; + + /* Turn off recording before playback */ + priv->recording = FALSE; + + /* Move the recorded instructions to a separate list and get them out of the private data + * structure. If there are nested loops, the shader_arb_handle_instruction below will + * be recorded again, thus priv->record might be overwritten + */ + list_init(©); + list_move_tail(©, &priv->record); + list_init(&priv->record); + + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + shader_addline(buffer, "#unrolling loop: %u iterations, aL=%u, inc %d\n", + control_frame->loop_control.count, control_frame->loop_control.start, + control_frame->loop_control.step); + aL = control_frame->loop_control.start; + } + else + { + shader_addline(buffer, "#unrolling rep: %u iterations\n", control_frame->loop_control.count); + } + + for (iteration = 0; iteration < control_frame->loop_control.count; ++iteration) + { + struct recorded_instruction *rec_ins; + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + priv->aL = aL; + shader_addline(buffer, "#Iteration %d, aL=%d\n", iteration, aL); + } + else + { + shader_addline(buffer, "#Iteration %d\n", iteration); + } + + LIST_FOR_EACH_ENTRY(rec_ins, ©, struct recorded_instruction, entry) + { + shader_arb_handle_instruction(&rec_ins->ins); + } + + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + aL += control_frame->loop_control.step; + } + } + shader_addline(buffer, "#end loop/rep\n"); + + free_recorded_instruction(©); + HeapFree(GetProcessHeap(), 0, control_frame); + return; /* Instruction is handled */ + } + else + { + /* This is a nested loop. Proceed to the normal recording function */ + HeapFree(GetProcessHeap(), 0, control_frame); + } + } + } + + if(priv->recording) + { + record_instruction(&priv->record, ins); + return; + } + + /* boolean if */ + if(ins->handler_idx == WINED3DSIH_IF) + { + control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); + list_add_head(&priv->control_frames, &control_frame->entry); + control_frame->type = IF; + + bool_const = get_bool_const(ins, This, ins->src[0].reg.idx); + if(ins->src[0].modifiers == WINED3DSPSM_NOT) bool_const = !bool_const; + if(!priv->muted && bool_const == FALSE) + { + shader_addline(buffer, "#if(FALSE){\n"); + priv->muted = TRUE; + control_frame->muting = TRUE; + } + else shader_addline(buffer, "#if(TRUE) {\n"); + + return; /* Instruction is handled */ + } + else if(ins->handler_idx == WINED3DSIH_IFC) + { + /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */ + control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); + control_frame->type = IFC; + control_frame->ifc_no = priv->num_ifcs++; + list_add_head(&priv->control_frames, &control_frame->entry); + } + else if(ins->handler_idx == WINED3DSIH_ELSE) + { + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + + if(control_frame->type == IF) + { + shader_addline(buffer, "#} else {\n"); + if(!priv->muted && !control_frame->muting) + { + priv->muted = TRUE; + control_frame->muting = TRUE; + } + else if(control_frame->muting) priv->muted = FALSE; + return; /* Instruction is handled. */ + } + /* In case of an ifc, generate a HW shader instruction */ + } + else if(ins->handler_idx == WINED3DSIH_ENDIF) + { + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + + if(control_frame->type == IF) + { + shader_addline(buffer, "#} endif\n"); + if(control_frame->muting) priv->muted = FALSE; + list_remove(&control_frame->entry); + HeapFree(GetProcessHeap(), 0, control_frame); + return; /* Instruction is handled */ + } + } + + if(priv->muted) return; + + /* Select handler */ + hw_fct = shader_arb_instruction_handler_table[ins->handler_idx]; + + /* Unhandled opcode */ + if (!hw_fct) + { + FIXME("Backend can't handle opcode %#x\n", ins->handler_idx); + return; + } + hw_fct(ins); + + if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP) + { + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + list_remove(&control_frame->entry); + HeapFree(GetProcessHeap(), 0, control_frame); + priv->loop_depth--; + } + else if(ins->handler_idx == WINED3DSIH_ENDIF) + { + /* Non-ifc ENDIFs don't reach that place because of the return in the if block above */ + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + list_remove(&control_frame->entry); + HeapFree(GetProcessHeap(), 0, control_frame); + } + + + shader_arb_add_instruction_modifiers(ins); +} + const shader_backend_t arb_program_shader_backend = { - shader_arb_instruction_handler_table, + shader_arb_handle_instruction, shader_arb_select, shader_arb_select_depth_blt, shader_arb_deselect_depth_blt, @@ -2265,11 +5016,8 @@ const shader_backend_t arb_program_shader_backend = { shader_arb_alloc, shader_arb_free, shader_arb_dirty_const, - shader_arb_generate_pshader, - shader_arb_generate_vshader, shader_arb_get_caps, shader_arb_color_fixup_supported, - shader_arb_add_instruction_modifiers, }; /* ARB_fragment_program fixed function pipeline replacement definitions */ @@ -2286,7 +5034,9 @@ struct arbfp_ffp_desc unsigned int num_textures_used; }; +/* Context activation is done by the caller. */ static void arbfp_enable(IWineD3DDevice *iface, BOOL enable) { + ENTER_GL(); if(enable) { glEnable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)"); @@ -2294,6 +5044,7 @@ static void arbfp_enable(IWineD3DDevice *iface, BOOL enable) { glDisable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); } + LEAVE_GL(); } static HRESULT arbfp_alloc(IWineD3DDevice *iface) { @@ -2310,14 +5061,21 @@ static HRESULT arbfp_alloc(IWineD3DDevice *iface) { if(!This->fragment_priv) return E_OUTOFMEMORY; } priv = This->fragment_priv; - priv->fragment_shaders = hash_table_create(ffp_frag_program_key_hash, ffp_frag_program_key_compare); + if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1) + { + ERR("Failed to initialize rbtree.\n"); + HeapFree(GetProcessHeap(), 0, This->fragment_priv); + return E_OUTOFMEMORY; + } priv->use_arbfp_fixed_func = TRUE; return WINED3D_OK; } -static void arbfp_free_ffpshader(void *value, void *gli) { - const WineD3D_GL_Info *gl_info = gli; - struct arbfp_ffp_desc *entry_arb = value; +/* Context activation is done by the caller. */ +static void arbfp_free_ffpshader(struct wine_rb_entry *entry, void *context) +{ + const struct wined3d_gl_info *gl_info = context; + struct arbfp_ffp_desc *entry_arb = WINE_RB_ENTRY_VALUE(entry, struct arbfp_ffp_desc, parent.entry); ENTER_GL(); GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader)); @@ -2326,11 +5084,12 @@ static void arbfp_free_ffpshader(void *value, void *gli) { LEAVE_GL(); } +/* Context activation is done by the caller. */ static void arbfp_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; struct shader_arb_priv *priv = This->fragment_priv; - hash_table_destroy(priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info); + wine_rb_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) { @@ -2338,7 +5097,7 @@ static void arbfp_free(IWineD3DDevice *iface) { } } -static void arbfp_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *caps) +static void arbfp_get_caps(WINED3DDEVTYPE devtype, const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) { caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | WINED3DTEXOPCAPS_SELECTARG1 | @@ -2376,7 +5135,8 @@ static void arbfp_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_inf #undef GLINFO_LOCATION #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info -static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; @@ -2387,7 +5147,7 @@ static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *statebloc if (use_ps(stateblock)) return; device = stateblock->wineD3DDevice; - device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1; + context->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1; device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1); } @@ -2397,7 +5157,8 @@ static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *statebloc } -static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; @@ -2408,31 +5169,33 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb if (use_ps(stateblock)) return; device = stateblock->wineD3DDevice; - device->activeContext->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1; + context->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); } 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; + col[0] = 1.0f; col[1] = 1.0f; + col[2] = 1.0f; col[3] = 0.0f; } else { - col[0] = 0.0; col[1] = 0.0; - col[2] = 0.0; col[3] = 0.0; + col[0] = 0.0f; col[1] = 0.0f; + col[2] = 0.0f; col[3] = 0.0f; } 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)"); } -static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; float mat[2][2]; if (use_ps(stateblock)) { - if(stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) { + if (stage != 0 + && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage))) + { /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled * anyway */ @@ -2446,7 +5209,7 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, W return; } } else if(device->shader_backend == &arb_program_shader_backend) { - device->activeContext->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1; + context->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); } @@ -2459,15 +5222,17 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, W checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])"); } -static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; float param[4]; if (use_ps(stateblock)) { - if(stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) { + if (stage != 0 + && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage))) + { /* The pixel shader has to know the luminance offset. Do a constants update if it * isn't scheduled anyway */ @@ -2481,20 +5246,21 @@ static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock return; } } else if(device->shader_backend == &arb_program_shader_backend) { - device->activeContext->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1; + context->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); } param[0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]); param[1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]); - param[2] = 0.0; - param[3] = 0.0; + param[2] = 0.0f; + param[3] = 0.0f; 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)"); } -static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int stage, DWORD arg) { +static const char *get_argreg(struct wined3d_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 */ @@ -2565,8 +5331,9 @@ static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int 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) { +static void gen_ffp_instr(struct wined3d_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; @@ -2707,7 +5474,7 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color, static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWineD3DStateBlockImpl *stateblock) { unsigned int stage; - SHADER_BUFFER buffer; + struct wined3d_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}; @@ -2770,7 +5537,11 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi } /* Shader header */ - shader_buffer_init(&buffer); + if (!shader_buffer_init(&buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + return 0; + } shader_addline(&buffer, "!!ARBfp1.0\n"); @@ -2809,6 +5580,8 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi srgb_sub_high, 0.0, 0.0, 0.0); } + if(ffp_clip_emul(stateblock) && settings->emul_clipplanes) shader_addline(&buffer, "KIL fragment.texcoord[7];\n"); + /* Generate texture sampling instructions) */ for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) { if(!tex_read[stage]) continue; @@ -2935,8 +5708,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi 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.w, ret.w;\n"); + arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg", FALSE); } else { shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src); } @@ -2959,7 +5731,8 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi return ret; } -static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; struct shader_arb_priv *priv = device->fragment_priv; BOOL use_pshader = use_ps(stateblock); @@ -2979,7 +5752,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context); state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context); } else if(use_pshader && !isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { - device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader); + device->shader_backend->shader_select(context, use_pshader, use_vshader); } return; } @@ -2987,7 +5760,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, if(!use_pshader) { /* Find or create a shader implementing the fixed function pipeline settings, then activate it */ gen_ffp_frag_op(stateblock, &settings, FALSE); - desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(priv->fragment_shaders, &settings); + desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings); if(!desc) { struct arbfp_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc)); if (!new_desc) @@ -3003,7 +5776,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, memcpy(&new_desc->parent.settings, &settings, sizeof(settings)); new_desc->shader = gen_arbfp_ffp_shader(&settings, stateblock); - add_ffp_frag_shader(priv->fragment_shaders, &new_desc->parent); + add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent); TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc); desc = new_desc; } @@ -3039,7 +5812,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, * shader handler */ if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { - device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader); + device->shader_backend->shader_select(context, use_pshader, use_vshader); if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context); @@ -3056,7 +5829,8 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, * 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) { +static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ enum fogsource new_source; TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); @@ -3086,7 +5860,8 @@ static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(!isStateDirty(context, STATE_PIXELSHADER)) { fragment_prog_arbfp(state, stateblock, context); } @@ -3095,154 +5870,154 @@ static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3 #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_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, - {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, - {STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, - {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 }, - {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 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 }, + {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlum_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_PIXELSHADER, { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_arb_specularenable}, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; const struct fragment_pipeline arbfp_fragment_pipeline = { @@ -3272,6 +6047,8 @@ static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) { } return WINED3D_OK; } + +/* Context activation is done by the caller. */ static void arbfp_blit_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; struct arbfp_blit_priv *priv = device->blit_priv; @@ -3283,11 +6060,12 @@ static void arbfp_blit_free(IWineD3DDevice *iface) { 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"); + checkGLcall("Delete yuv programs"); LEAVE_GL(); } -static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup, GLenum textype, char *luminance) +static BOOL gen_planar_yuv_read(struct wined3d_shader_buffer *buffer, enum yuv_fixup yuv_fixup, + GLenum textype, char *luminance) { char chroma; const char *tex, *texinstr; @@ -3374,7 +6152,7 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup, return TRUE; } -static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance) +static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, char *luminance) { const char *tex; @@ -3425,7 +6203,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance * 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); + 2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f); shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n"); /* the chroma planes have only half the width */ @@ -3520,15 +6298,20 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance return TRUE; } +/* Context activation is done by the caller. */ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixup, GLenum textype) { GLenum shader; - SHADER_BUFFER buffer; + struct wined3d_shader_buffer buffer; char luminance_component; struct arbfp_blit_priv *priv = device->blit_priv; /* Shader header */ - shader_buffer_init(&buffer); + if (!shader_buffer_init(&buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + return 0; + } ENTER_GL(); GL_EXTCALL(glGenProgramsARB(1, &shader)); @@ -3656,6 +6439,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu return shader; } +/* Context activation is done by the caller. */ static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatDesc *format_desc, GLenum textype, UINT width, UINT height) { @@ -3716,6 +6500,7 @@ static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatD return WINED3D_OK; } +/* Context activation is done by the caller. */ static void arbfp_blit_unset(IWineD3DDevice *iface) { IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; diff --git a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c index a8c137f9b45..aea942cc47e 100644 --- a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c +++ b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -28,6 +28,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); WINE_DECLARE_DEBUG_CHANNEL(d3d); +/* GL locking for state handlers is done by the caller. */ + /* 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 @@ -51,8 +53,7 @@ struct atifs_ffp_desc struct atifs_private_data { - struct hash_table_t *fragment_shaders; /* A hashtable to track fragment pipeline replacement shaders */ - + struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */ }; static const char *debug_dstmod(GLuint mod) { @@ -191,8 +192,9 @@ static const char *debug_mask(GLuint mask) { } #define GLINFO_LOCATION (*gl_info) -static void wrap_op1(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, - GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) { +static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, + GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ if(dstMask == GL_ALPHA) { TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod)); @@ -205,9 +207,9 @@ static void wrap_op1(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLui } } -static void wrap_op2(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, - GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, - GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) { +static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, + GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ if(dstMask == GL_ALPHA) { TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod), @@ -222,10 +224,10 @@ static void wrap_op2(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLui } } -static void wrap_op3(const WineD3D_GL_Info *gl_info, GLuint 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) { +static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint 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) +{ if(dstMask == GL_ALPHA) { /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */ TRACE("glAlphaFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), @@ -249,7 +251,7 @@ static void wrap_op3(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLui } } -static GLuint register_for_arg(DWORD arg, const WineD3D_GL_Info *gl_info, +static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info, unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg) { GLenum ret; @@ -377,7 +379,7 @@ static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES]) } } -static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const WineD3D_GL_Info *gl_info) +static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info) { GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1)); unsigned int stage; @@ -422,13 +424,6 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con 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 */ @@ -459,22 +454,24 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con 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 :-( + /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha + * component of the bump matrix. Instead do this with two MADs: * - * 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. + * coord.a = tex.r * bump.b + coord.g + * coord.g = tex.g * bump.a + coord.a + * + * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD. + * coord.a is unused. If the perturbed texture is projected, this was already handled + * in the glPassTexCoordATI above. */ - wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, - ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE); - wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, - ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE); - wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE, - GL_REG_0_ATI + stage, GL_NONE, argmodextra_y, - GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI, + wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE, + GL_REG_0_ATI + stage, GL_RED, argmodextra_y, + ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE, GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE); + wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE, + GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y, + ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE, + GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE); } /* Pass 3: Generate sampling instructions for regular textures */ @@ -799,7 +796,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con #undef GLINFO_LOCATION #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info -static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *This = stateblock->wineD3DDevice; const struct atifs_ffp_desc *desc; struct ffp_frag_settings settings; @@ -808,7 +806,7 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi unsigned int i; gen_ffp_frag_op(stateblock, &settings, TRUE); - desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(priv->fragment_shaders, &settings); + desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings); if(!desc) { struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc)); if (!new_desc) @@ -824,7 +822,7 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi memcpy(&new_desc->parent.settings, &settings, sizeof(settings)); new_desc->shader = gen_ati_shader(settings.op, &GLINFO_LOCATION); - add_ffp_frag_shader(priv->fragment_shaders, &new_desc->parent); + add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent); TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc); desc = new_desc; } @@ -845,7 +843,8 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi GL_EXTCALL(glBindFragmentShaderATI(desc->shader)); } -static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); @@ -853,7 +852,8 @@ static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *statebloc checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)"); } -static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); float mat[2][2]; @@ -868,21 +868,23 @@ static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D * 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; + mat[0][0] = (mat[0][0] + 1.0f) * 0.5f; + mat[1][0] = (mat[1][0] + 1.0f) * 0.5f; + mat[0][1] = (mat[0][1] + 1.0f) * 0.5f; + mat[1][1] = (mat[1][1] + 1.0f) * 0.5f; 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) { +static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(!isStateDirty(context, STATE_PIXELSHADER)) { set_tex_op_atifs(state, stateblock, context); } } -static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL use_vshader = use_vs(stateblock); @@ -899,7 +901,7 @@ static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *statebl * simpler. */ if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { - device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, use_vshader); + device->shader_backend->shader_select(context, FALSE, use_vshader); if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) { device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context); @@ -910,139 +912,141 @@ static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *statebl #undef GLINFO_LOCATION static const struct StateEntryTemplate atifs_fragmentstate_template[] = { - {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, 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_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, - {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 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 }, - {STATE_PIXELSHADER, { STATE_PIXELSHADER, atifs_apply_pixelshader }, 0 }, - {0 /* Terminate */, { 0, 0 }, 0 }, + {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, WINED3D_GL_EXT_NONE }, + {STATE_PIXELSHADER, { STATE_PIXELSHADER, atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; +/* Context activation is done by the caller. */ static void atifs_enable(IWineD3DDevice *iface, BOOL enable) { + ENTER_GL(); if(enable) { glEnable(GL_FRAGMENT_SHADER_ATI); checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)"); @@ -1050,9 +1054,10 @@ static void atifs_enable(IWineD3DDevice *iface, BOOL enable) { glDisable(GL_FRAGMENT_SHADER_ATI); checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)"); } + LEAVE_GL(); } -static void atifs_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *caps) +static void atifs_get_caps(WINED3DDEVTYPE devtype, const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) { caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | WINED3DTEXOPCAPS_SELECTARG1 | @@ -1110,14 +1115,21 @@ static HRESULT atifs_alloc(IWineD3DDevice *iface) { return E_OUTOFMEMORY; } priv = This->fragment_priv; - priv->fragment_shaders = hash_table_create(ffp_frag_program_key_hash, ffp_frag_program_key_compare); + if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1) + { + ERR("Failed to initialize rbtree.\n"); + HeapFree(GetProcessHeap(), 0, This->fragment_priv); + return E_OUTOFMEMORY; + } 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; +/* Context activation is done by the caller. */ +static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context) +{ + IWineD3DDeviceImpl *This = context; + struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry); ENTER_GL(); GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader)); @@ -1126,11 +1138,12 @@ static void atifs_free_ffpshader(void *value, void *device) { LEAVE_GL(); } +/* Context activation is done by the caller. */ static void atifs_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; struct atifs_private_data *priv = This->fragment_priv; - hash_table_destroy(priv->fragment_shaders, atifs_free_ffpshader, This); + wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, This); HeapFree(GetProcessHeap(), 0, priv); This->fragment_priv = NULL; diff --git a/reactos/dll/directx/wine/wined3d/baseshader.c b/reactos/dll/directx/wine/wined3d/baseshader.c index 8b8aef4d15a..c983e80a35a 100644 --- a/reactos/dll/directx/wine/wined3d/baseshader.c +++ b/reactos/dll/directx/wine/wined3d/baseshader.c @@ -138,35 +138,41 @@ const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token } } -static inline BOOL shader_is_version_token(DWORD token) { - return shader_is_pshader_version(token) || - shader_is_vshader_version(token); -} - -void shader_buffer_init(struct SHADER_BUFFER *buffer) +void shader_buffer_clear(struct wined3d_shader_buffer *buffer) { - buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE); buffer->buffer[0] = '\0'; buffer->bsize = 0; buffer->lineNo = 0; buffer->newline = TRUE; } -void shader_buffer_free(struct SHADER_BUFFER *buffer) +BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer) +{ + buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE); + if (!buffer->buffer) + { + ERR("Failed to allocate shader buffer memory.\n"); + return FALSE; + } + + shader_buffer_clear(buffer); + return TRUE; +} + +void shader_buffer_free(struct wined3d_shader_buffer *buffer) { HeapFree(GetProcessHeap(), 0, buffer->buffer); } -int shader_vaddline(SHADER_BUFFER* buffer, const char *format, va_list args) +int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args) { char* base = buffer->buffer + buffer->bsize; int rc; rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args); - if (rc < 0 || /* C89 */ - rc > SHADER_PGMSIZE - 1 - buffer->bsize) { /* C99 */ - + if (rc < 0 /* C89 */ || (unsigned int)rc > SHADER_PGMSIZE - 1 - buffer->bsize /* C99 */) + { ERR("The buffer allocated for the shader program string " "is too small at %d bytes.\n", SHADER_PGMSIZE); buffer->bsize = SHADER_PGMSIZE - 1; @@ -188,7 +194,7 @@ int shader_vaddline(SHADER_BUFFER* buffer, const char *format, va_list args) return 0; } -int shader_addline(SHADER_BUFFER* buffer, const char *format, ...) +int shader_addline(struct wined3d_shader_buffer *buffer, const char *format, ...) { int ret; va_list args; @@ -246,24 +252,23 @@ static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit) } static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct shader_reg_maps *reg_maps, - DWORD register_type, UINT register_idx, BOOL has_rel_addr, BOOL pshader) + const struct wined3d_shader_register *reg, enum wined3d_shader_type shader_type) { - switch (register_type) + switch (reg->type) { case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */ - if (pshader) reg_maps->texcoord[register_idx] = 1; - else reg_maps->address[register_idx] = 1; + if (shader_type == WINED3D_SHADER_TYPE_PIXEL) reg_maps->texcoord |= 1 << reg->idx; + else reg_maps->address |= 1 << reg->idx; break; case WINED3DSPR_TEMP: - reg_maps->temporary[register_idx] = 1; + reg_maps->temporary |= 1 << reg->idx; break; case WINED3DSPR_INPUT: - if (!pshader) reg_maps->attributes[register_idx] = 1; - else + if (shader_type == WINED3D_SHADER_TYPE_PIXEL) { - if (has_rel_addr) + if (reg->rel_addr) { /* If relative addressing is used, we must assume that all registers * are used. Even if it is a construct like v3[aL], we can't assume @@ -276,84 +281,142 @@ static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct sh } else { - ((IWineD3DPixelShaderImpl *)This)->input_reg_used[register_idx] = TRUE; + ((IWineD3DPixelShaderImpl *)This)->input_reg_used[reg->idx] = TRUE; } } + else reg_maps->input_registers |= 1 << reg->idx; break; case WINED3DSPR_RASTOUT: - if (register_idx == 1) reg_maps->fog = 1; + if (reg->idx == 1) reg_maps->fog = 1; break; case WINED3DSPR_MISCTYPE: - if (pshader && register_idx == 0) reg_maps->vpos = 1; + if (shader_type == WINED3D_SHADER_TYPE_PIXEL) + { + if (reg->idx == 0) reg_maps->vpos = 1; + else if (reg->idx == 1) reg_maps->usesfacing = 1; + } break; case WINED3DSPR_CONST: - if (has_rel_addr) + if (reg->rel_addr) { - if (!pshader) + if (shader_type != WINED3D_SHADER_TYPE_PIXEL) { - if (register_idx <= ((IWineD3DVertexShaderImpl *)This)->min_rel_offset) - ((IWineD3DVertexShaderImpl *)This)->min_rel_offset = register_idx; - else if (register_idx >= ((IWineD3DVertexShaderImpl *)This)->max_rel_offset) - ((IWineD3DVertexShaderImpl *)This)->max_rel_offset = register_idx; + if (reg->idx < ((IWineD3DVertexShaderImpl *)This)->min_rel_offset) + { + ((IWineD3DVertexShaderImpl *)This)->min_rel_offset = reg->idx; + } + if (reg->idx > ((IWineD3DVertexShaderImpl *)This)->max_rel_offset) + { + ((IWineD3DVertexShaderImpl *)This)->max_rel_offset = reg->idx; + } } reg_maps->usesrelconstF = TRUE; } else { - set_bitmap_bit(reg_maps->constf, register_idx); + set_bitmap_bit(reg_maps->constf, reg->idx); } break; case WINED3DSPR_CONSTINT: - reg_maps->integer_constants |= (1 << register_idx); + reg_maps->integer_constants |= (1 << reg->idx); break; case WINED3DSPR_CONSTBOOL: - reg_maps->boolean_constants |= (1 << register_idx); + reg_maps->boolean_constants |= (1 << reg->idx); + break; + + case WINED3DSPR_COLOROUT: + reg_maps->highest_render_target = max(reg_maps->highest_render_target, reg->idx); break; default: - TRACE("Not recording register of type %#x and idx %u\n", register_type, register_idx); + TRACE("Not recording register of type %#x and idx %u\n", reg->type, reg->idx); break; } } -static unsigned char get_instr_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, int param) +static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param) { switch(instr) { case WINED3DSIH_M4x4: case WINED3DSIH_M3x4: - return param == 1 ? 4 : 1; + return param == 1 ? 3 : 0; case WINED3DSIH_M4x3: case WINED3DSIH_M3x3: - return param == 1 ? 3 : 1; + return param == 1 ? 2 : 0; case WINED3DSIH_M3x2: - return param == 1 ? 2 : 1; + return param == 1 ? 1 : 0; default: - return 1; + return 0; } } +static const char *shader_semantic_name_from_usage(WINED3DDECLUSAGE usage) +{ + static const char *semantic_names[] = + { + /* WINED3DDECLUSAGE_POSITION */ "SV_POSITION", + /* WINED3DDECLUSAGE_BLENDWEIGHT */ "BLENDWEIGHT", + /* WINED3DDECLUSAGE_BLENDINDICES */ "BLENDINDICES", + /* WINED3DDECLUSAGE_NORMAL */ "NORMAL", + /* WINED3DDECLUSAGE_PSIZE */ "PSIZE", + /* WINED3DDECLUSAGE_TEXCOORD */ "TEXCOORD", + /* WINED3DDECLUSAGE_TANGENT */ "TANGENT", + /* WINED3DDECLUSAGE_BINORMAL */ "BINORMAL", + /* WINED3DDECLUSAGE_TESSFACTOR */ "TESSFACTOR", + /* WINED3DDECLUSAGE_POSITIONT */ "POSITIONT", + /* WINED3DDECLUSAGE_COLOR */ "COLOR", + /* WINED3DDECLUSAGE_FOG */ "FOG", + /* WINED3DDECLUSAGE_DEPTH */ "DEPTH", + /* WINED3DDECLUSAGE_SAMPLE */ "SAMPLE", + }; + + if (usage >= sizeof(semantic_names) / sizeof(*semantic_names)) + { + FIXME("Unrecognized usage %#x\n", usage); + return "UNRECOGNIZED"; + } + + return semantic_names[usage]; +} + +BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage) +{ + return !strcmp(semantic_name, shader_semantic_name_from_usage(usage)); +} + +static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e, + const struct wined3d_shader_semantic *s) +{ + e->semantic_name = shader_semantic_name_from_usage(s->usage); + e->semantic_idx = s->usage_idx; + e->sysval_semantic = 0; + e->component_type = 0; + e->register_idx = s->reg.reg.idx; + e->mask = s->reg.write_mask; +} + /* Note that this does not count the loop register * as an address register. */ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe, - struct shader_reg_maps *reg_maps, struct wined3d_shader_semantic *semantics_in, - struct wined3d_shader_semantic *semantics_out, const DWORD *byte_code, DWORD constf_size) + struct shader_reg_maps *reg_maps, struct wined3d_shader_attribute *attributes, + struct wined3d_shader_signature_element *input_signature, + struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; void *fe_data = This->baseShader.frontend_data; struct wined3d_shader_version shader_version; unsigned int cur_loop_depth = 0, max_loop_depth = 0; const DWORD* pToken = byte_code; - char pshader; /* There are some minor differences between pixel and vertex shaders */ @@ -368,7 +431,6 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 fe->shader_read_header(fe_data, &pToken, &shader_version); reg_maps->shader_version = shader_version; - pshader = shader_is_pshader_version(shader_version.type); reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*reg_maps->constf) * ((constf_size + 31) / 32)); @@ -410,15 +472,22 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 /* Vshader: mark attributes used * Pshader: mark 3.0 input registers used, save token */ case WINED3DSPR_INPUT: - if (!pshader) reg_maps->attributes[semantic.reg.reg.idx] = 1; - else reg_maps->packed_input[semantic.reg.reg.idx] = 1; - semantics_in[semantic.reg.reg.idx] = semantic; + reg_maps->input_registers |= 1 << semantic.reg.reg.idx; + if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX) + { + attributes[semantic.reg.reg.idx].usage = semantic.usage; + attributes[semantic.reg.reg.idx].usage_idx = semantic.usage_idx; + } + else + { + shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic); + } break; /* Vshader: mark 3.0 output registers used, save token */ case WINED3DSPR_OUTPUT: - reg_maps->packed_output[semantic.reg.reg.idx] = 1; - semantics_out[semantic.reg.reg.idx] = semantic; + reg_maps->output_registers |= 1 << semantic.reg.reg.idx; + shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic); if (semantic.usage == WINED3DDECLUSAGE_FOG) reg_maps->fog = 1; break; @@ -447,17 +516,17 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 pToken += 4; /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */ - if (shader_version.major == 1 && pshader) + if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL) { float *value = (float *) lconst->value; - if(value[0] < -1.0) value[0] = -1.0; - else if(value[0] > 1.0) value[0] = 1.0; - if(value[1] < -1.0) value[1] = -1.0; - else if(value[1] > 1.0) value[1] = 1.0; - if(value[2] < -1.0) value[2] = -1.0; - else if(value[2] > 1.0) value[2] = 1.0; - if(value[3] < -1.0) value[3] = -1.0; - else if(value[3] > 1.0) value[3] = 1.0; + if (value[0] < -1.0f) value[0] = -1.0f; + else if (value[0] > 1.0f) value[0] = 1.0f; + if (value[1] < -1.0f) value[1] = -1.0f; + else if (value[1] > 1.0f) value[1] = 1.0f; + if (value[2] < -1.0f) value[2] = -1.0f; + else if (value[2] > 1.0f) value[2] = 1.0f; + if (value[3] < -1.0f) value[3] = -1.0f; + else if (value[3] > 1.0f) value[3] = 1.0f; } list_add_head(&This->baseShader.constantsF, &lconst->entry); @@ -477,6 +546,7 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 pToken += 4; list_add_head(&This->baseShader.constantsI, &lconst->entry); + reg_maps->local_int_consts |= (1 << dst.reg.idx); } else if (ins.handler_idx == WINED3DSIH_DEFB) { @@ -493,6 +563,7 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 ++pToken; list_add_head(&This->baseShader.constantsB, &lconst->entry); + reg_maps->local_bool_consts |= (1 << dst.reg.idx); } /* If there's a loop in the shader */ else if (ins.handler_idx == WINED3DSIH_LOOP @@ -528,12 +599,13 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 struct wined3d_shader_src_param src, rel_addr; fe->shader_read_src_param(fe_data, &pToken, &src, &rel_addr); - reg_maps->labels[src.reg.idx] = 1; + reg_maps->labels |= 1 << src.reg.idx; } /* Set texture, address, temporary registers */ else { int i, limit; + BOOL color0_mov = FALSE; /* This will loop over all the registers and try to * make a bitmask of the ones we're interested in. @@ -549,22 +621,49 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 fe->shader_read_dst_param(fe_data, &pToken, &dst_param, &dst_rel_addr); + shader_record_register_usage(This, reg_maps, &dst_param.reg, shader_version.type); + /* 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 */ - if (!pshader && shader_version.major < 3 && dst_param.reg.type == WINED3DSPR_TEXCRDOUT) + if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3 + && dst_param.reg.type == WINED3DSPR_TEXCRDOUT) { - reg_maps->texcoord_mask[dst_param.reg.type] |= dst_param.write_mask; + reg_maps->texcoord_mask[dst_param.reg.idx] |= dst_param.write_mask; } - else + + if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL) { - shader_record_register_usage(This, reg_maps, dst_param.reg.type, - dst_param.reg.idx, !!dst_param.reg.rel_addr, pshader); + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)This; + + if(dst_param.reg.type == WINED3DSPR_COLOROUT && dst_param.reg.idx == 0) + { + /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to + * COLOROUT 0. If we know this in advance, the ARB shader backend can skip + * the mov and perform the sRGB write correction from the source register. + * + * However, if the mov is only partial, we can't do this, and if the write + * comes from an instruction other than MOV it is hard to do as well. If + * COLOROUT 0 is overwritten partially later, the marker is dropped again. */ + + ps->color0_mov = FALSE; + if (ins.handler_idx == WINED3DSIH_MOV) + { + /* Used later when the source register is read. */ + color0_mov = TRUE; + } + } + /* Also drop the MOV marker if the source register is overwritten prior to the shader + * end + */ + else if(dst_param.reg.type == WINED3DSPR_TEMP && dst_param.reg.idx == ps->color0_reg) + { + ps->color0_mov = FALSE; + } } /* Declare 1.X samplers implicitly, based on the destination reg. number */ if (shader_version.major == 1 - && pshader /* Filter different instructions with the same enum values in VS */ && (ins.handler_idx == WINED3DSIH_TEX || ins.handler_idx == WINED3DSIH_TEXBEM || ins.handler_idx == WINED3DSIH_TEXBEML @@ -587,16 +686,16 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 if (ins.handler_idx == WINED3DSIH_TEXBEM || ins.handler_idx == WINED3DSIH_TEXBEML) { - reg_maps->bumpmat[sampler_code] = TRUE; + reg_maps->bumpmat |= 1 << dst_param.reg.idx; if (ins.handler_idx == WINED3DSIH_TEXBEML) { - reg_maps->luminanceparams[sampler_code] = TRUE; + reg_maps->luminanceparams |= 1 << dst_param.reg.idx; } } } - else if (pshader && ins.handler_idx == WINED3DSIH_BEM) + else if (ins.handler_idx == WINED3DSIH_BEM) { - reg_maps->bumpmat[dst_param.reg.idx] = TRUE; + reg_maps->bumpmat |= 1 << dst_param.reg.idx; } } @@ -608,45 +707,77 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 { reg_maps->usesdsy = 1; } + else if (ins.handler_idx == WINED3DSIH_DSX) + { + reg_maps->usesdsx = 1; + } else if(ins.handler_idx == WINED3DSIH_TEXLDD) { reg_maps->usestexldd = 1; } + else if(ins.handler_idx == WINED3DSIH_TEXLDL) + { + reg_maps->usestexldl = 1; + } + else if(ins.handler_idx == WINED3DSIH_MOVA) + { + reg_maps->usesmova = 1; + } + else if(ins.handler_idx == WINED3DSIH_IFC) + { + reg_maps->usesifc = 1; + } + else if(ins.handler_idx == WINED3DSIH_CALL) + { + reg_maps->usescall = 1; + } limit = ins.src_count + (ins.predicate ? 1 : 0); for (i = 0; i < limit; ++i) { struct wined3d_shader_src_param src_param, src_rel_addr; + unsigned int count; fe->shader_read_src_param(fe_data, &pToken, &src_param, &src_rel_addr); - switch(get_instr_regcount(ins.handler_idx, i)) + count = get_instr_extra_regcount(ins.handler_idx, i); + + shader_record_register_usage(This, reg_maps, &src_param.reg, shader_version.type); + while (count) { - case 4: - shader_record_register_usage(This, reg_maps, src_param.reg.type, - src_param.reg.idx + 3, !!src_param.reg.rel_addr, pshader); - /* drop through */ - case 3: - shader_record_register_usage(This, reg_maps, src_param.reg.type, - src_param.reg.idx + 2, !!src_param.reg.rel_addr, pshader); - /* drop through */ - case 2: - shader_record_register_usage(This, reg_maps, src_param.reg.type, - src_param.reg.idx + 1, !!src_param.reg.rel_addr, pshader); - /* drop through */ - case 1: - shader_record_register_usage(This, reg_maps, src_param.reg.type, - src_param.reg.idx, !!src_param.reg.rel_addr, pshader); + ++src_param.reg.idx; + shader_record_register_usage(This, reg_maps, &src_param.reg, shader_version.type); + --count; + } + + if(color0_mov) + { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This; + if(src_param.reg.type == WINED3DSPR_TEMP && + src_param.swizzle == WINED3DSP_NOSWIZZLE) + { + ps->color0_mov = TRUE; + ps->color0_reg = src_param.reg.idx; + } } } } } reg_maps->loop_depth = max_loop_depth; - This->baseShader.functionLength = ((char *)pToken - (char *)byte_code); + This->baseShader.functionLength = ((const char *)pToken - (const char *)byte_code); return WINED3D_OK; } +unsigned int shader_find_free_input_register(const struct shader_reg_maps *reg_maps, unsigned int max) +{ + DWORD map = 1 << max; + map |= map - 1; + map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers; + + return wined3d_log2i(map); +} + static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic, const struct wined3d_shader_version *shader_version) { @@ -665,7 +796,7 @@ static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semanti else { /* Pixel shaders 3.0 don't have usage semantics */ - if (shader_is_pshader_version(shader_version->type) && shader_version->major < 3) + if (shader_version->major < 3 && shader_version->type == WINED3D_SHADER_TYPE_PIXEL) return; else TRACE("_"); @@ -721,15 +852,14 @@ static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semanti } } -static void shader_dump_register(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx, - enum wined3d_immconst_type immconst_type, const DWORD *immconst_data, - const struct wined3d_shader_src_param *rel_addr, const struct wined3d_shader_version *shader_version) +static void shader_dump_register(const struct wined3d_shader_register *reg, + const struct wined3d_shader_version *shader_version) { static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"}; static const char * const misctype_reg_names[] = {"vPos", "vFace"}; - UINT offset = register_idx; + UINT offset = reg->idx; - switch (register_type) + switch (reg->type) { case WINED3DSPR_TEMP: TRACE("r"); @@ -744,15 +874,15 @@ static void shader_dump_register(WINED3DSHADER_PARAM_REGISTER_TYPE register_type case WINED3DSPR_CONST3: case WINED3DSPR_CONST4: TRACE("c"); - offset = shader_get_float_offset(register_type, register_idx); + offset = shader_get_float_offset(reg->type, reg->idx); break; case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */ - TRACE("%c", shader_is_pshader_version(shader_version->type) ? 't' : 'a'); + TRACE("%c", shader_version->type == WINED3D_SHADER_TYPE_PIXEL ? 't' : 'a'); break; case WINED3DSPR_RASTOUT: - TRACE("%s", rastout_reg_names[register_idx]); + TRACE("%s", rastout_reg_names[reg->idx]); break; case WINED3DSPR_COLOROUT: @@ -795,8 +925,8 @@ static void shader_dump_register(WINED3DSHADER_PARAM_REGISTER_TYPE register_type break; case WINED3DSPR_MISCTYPE: - if (register_idx > 1) FIXME("Unhandled misctype register %d\n", register_idx); - else TRACE("%s", misctype_reg_names[register_idx]); + if (reg->idx > 1) FIXME("Unhandled misctype register %d\n", reg->idx); + else TRACE("%s", misctype_reg_names[reg->idx]); break; case WINED3DSPR_PREDICATE: @@ -807,42 +937,59 @@ static void shader_dump_register(WINED3DSHADER_PARAM_REGISTER_TYPE register_type TRACE("l"); break; + case WINED3DSPR_CONSTBUFFER: + TRACE("cb"); + break; + default: - TRACE("unhandled_rtype(%#x)", register_type); + TRACE("unhandled_rtype(%#x)", reg->type); break; } - if (register_type == WINED3DSPR_IMMCONST) + if (reg->type == WINED3DSPR_IMMCONST) { TRACE("("); - switch (immconst_type) + switch (reg->immconst_type) { case WINED3D_IMMCONST_FLOAT: - TRACE("%.8e", *(float *)immconst_data); + TRACE("%.8e", *(const float *)reg->immconst_data); break; case WINED3D_IMMCONST_FLOAT4: TRACE("%.8e, %.8e, %.8e, %.8e", - *(float *)&immconst_data[0], *(float *)&immconst_data[1], - *(float *)&immconst_data[2], *(float *)&immconst_data[3]); + *(const float *)®->immconst_data[0], *(const float *)®->immconst_data[1], + *(const float *)®->immconst_data[2], *(const float *)®->immconst_data[3]); break; default: - TRACE("", immconst_type); + TRACE("", reg->immconst_type); break; } TRACE(")"); } - else if (register_type != WINED3DSPR_RASTOUT && register_type != WINED3DSPR_MISCTYPE) + else if (reg->type != WINED3DSPR_RASTOUT && reg->type != WINED3DSPR_MISCTYPE) { - if (rel_addr) + if (reg->array_idx != ~0U) { - TRACE("["); - shader_dump_src_param(rel_addr, shader_version); - TRACE(" + "); + TRACE("%u[%u", offset, reg->array_idx); + if (reg->rel_addr) + { + TRACE(" + "); + shader_dump_src_param(reg->rel_addr, shader_version); + } + TRACE("]"); + } + else + { + if (reg->rel_addr) + { + TRACE("["); + shader_dump_src_param(reg->rel_addr, shader_version); + TRACE(" + "); + } + TRACE("%u", offset); + if (reg->rel_addr) TRACE("]"); } - TRACE("%u", offset); - if (rel_addr) TRACE("]"); } } @@ -851,7 +998,7 @@ void shader_dump_dst_param(const struct wined3d_shader_dst_param *param, { DWORD write_mask = param->write_mask; - shader_dump_register(param->reg.type, param->reg.idx, 0, NULL, param->reg.rel_addr, shader_version); + shader_dump_register(¶m->reg, shader_version); if (write_mask != WINED3DSP_WRITEMASK_ALL) { @@ -885,8 +1032,7 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param, if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG) TRACE("abs("); - shader_dump_register(param->reg.type, param->reg.idx, param->reg.immconst_type, - param->reg.immconst_data, param->reg.rel_addr, shader_version); + shader_dump_register(¶m->reg, shader_version); if (src_modifier) { @@ -935,12 +1081,11 @@ void shader_dump_src_param(const struct wined3d_shader_src_param *param, /* Shared code in order to generate the bulk of the shader string. * NOTE: A description of how to parse tokens can be found on msdn */ -void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, - const shader_reg_maps *reg_maps, const DWORD *pFunction) +void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffer *buffer, + const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */ - const SHADER_HANDLER *handler_table = device->shader_backend->shader_instruction_handler_table; const struct wined3d_shader_frontend *fe = This->baseShader.frontend; void *fe_data = This->baseShader.frontend_data; struct wined3d_shader_src_param src_rel_addr[4]; @@ -951,13 +1096,13 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, struct wined3d_shader_instruction ins; struct wined3d_shader_context ctx; const DWORD *pToken = pFunction; - SHADER_HANDLER hw_fct; DWORD i; /* Initialize current parsing state */ ctx.shader = iface; ctx.reg_maps = reg_maps; ctx.buffer = buffer; + ctx.backend_data = backend_ctx; ins.ctx = &ctx; ins.dst = &dst_param; @@ -992,24 +1137,12 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, || ins.handler_idx == WINED3DSIH_DEF || ins.handler_idx == WINED3DSIH_DEFI || ins.handler_idx == WINED3DSIH_DEFB - || ins.handler_idx == WINED3DSIH_PHASE - || ins.handler_idx == WINED3DSIH_RET) + || ins.handler_idx == WINED3DSIH_PHASE) { pToken += param_size; continue; } - /* Select handler */ - hw_fct = handler_table[ins.handler_idx]; - - /* Unhandled opcode */ - if (!hw_fct) - { - FIXME("Backend can't handle opcode %#x\n", ins.handler_idx); - pToken += param_size; - continue; - } - /* Destination token */ if (ins.dst_count) fe->shader_read_dst_param(fe_data, &pToken, &dst_param, &dst_rel_addr); @@ -1023,10 +1156,7 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, } /* Call appropriate function for output target */ - hw_fct(&ins); - - /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */ - device->shader_backend->shader_add_instruction_modifiers(&ins); + device->shader_backend->shader_handle_instruction(&ins); } } @@ -1059,14 +1189,34 @@ void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, { struct wined3d_shader_version shader_version; const DWORD* pToken = pFunction; + const char *type_prefix; DWORD i; TRACE("Parsing %p\n", pFunction); fe->shader_read_header(fe_data, &pToken, &shader_version); - TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version.type) ? "ps": "vs", - shader_version.major, shader_version.minor); + switch (shader_version.type) + { + case WINED3D_SHADER_TYPE_VERTEX: + type_prefix = "vs"; + break; + + case WINED3D_SHADER_TYPE_GEOMETRY: + type_prefix = "gs"; + break; + + case WINED3D_SHADER_TYPE_PIXEL: + type_prefix = "ps"; + break; + + default: + FIXME("Unhandled shader type %#x.\n", shader_version.type); + type_prefix = "unknown"; + break; + } + + TRACE("%s_%u_%u\n", type_prefix, shader_version.major, shader_version.minor); while (!fe->shader_is_end(fe_data, &pToken)) { @@ -1224,39 +1374,27 @@ void shader_cleanup(IWineD3DBaseShader *iface) } } -static const SHADER_HANDLER shader_none_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = {0}; -static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {} +static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {} +static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {} static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {} static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {} static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {} -static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {} +static void shader_none_load_constants(const struct wined3d_context *context, char usePS, char useVS) {} static void shader_none_load_np2fixup_constants(IWineD3DDevice *iface, char usePS, char useVS) {} 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 GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, - SHADER_BUFFER *buffer, const struct ps_compile_args *args) -{ - FIXME("NONE shader backend asked to generate a pixel shader\n"); - return 0; -} -static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args) -{ - FIXME("NONE shader backend asked to generate a vertex shader\n"); - return 0; -} -static void shader_none_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {} #define GLINFO_LOCATION (*gl_info) -static void shader_none_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) +static void shader_none_get_caps(WINED3DDEVTYPE devtype, + const struct 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; + pCaps->PixelShader1xMaxValue = 0.0f; } #undef GLINFO_LOCATION static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup) @@ -1279,7 +1417,7 @@ static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup) } const shader_backend_t none_shader_backend = { - shader_none_instruction_handler_table, + shader_none_handle_instruction, shader_none_select, shader_none_select_depth_blt, shader_none_deselect_depth_blt, @@ -1291,9 +1429,6 @@ const shader_backend_t none_shader_backend = { shader_none_alloc, shader_none_free, shader_none_dirty_const, - shader_none_generate_pshader, - shader_none_generate_vshader, shader_none_get_caps, shader_none_color_fixup_supported, - shader_none_add_instruction_modifiers, }; diff --git a/reactos/dll/directx/wine/wined3d/basetexture.c b/reactos/dll/directx/wine/wined3d/basetexture.c index caf2148ba55..ab38b625aae 100644 --- a/reactos/dll/directx/wine/wined3d/basetexture.c +++ b/reactos/dll/directx/wine/wined3d/basetexture.c @@ -27,32 +27,44 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info -void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage) +HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type, + IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, + WINED3DPOOL pool, IUnknown *parent) { - texture->levels = levels; - texture->filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; - texture->LOD = 0; - texture->dirty = TRUE; - texture->srgbDirty = TRUE; - texture->is_srgb = FALSE; - texture->pow2Matrix_identity = TRUE; + HRESULT hr; + + hr = resource_init((IWineD3DResource *)texture, resource_type, device, size, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + return hr; + } + + texture->baseTexture.levels = levels; + texture->baseTexture.filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; + texture->baseTexture.LOD = 0; + texture->baseTexture.dirty = TRUE; + texture->baseTexture.srgbDirty = TRUE; + texture->baseTexture.is_srgb = FALSE; + texture->baseTexture.pow2Matrix_identity = TRUE; + + if (texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) + { + texture->baseTexture.minMipLookup = minMipLookup; + texture->baseTexture.magLookup = magLookup; + } + else + { + texture->baseTexture.minMipLookup = minMipLookup_noFilter; + texture->baseTexture.magLookup = magLookup_noFilter; + } + + return WINED3D_OK; } void basetexture_cleanup(IWineD3DBaseTexture *iface) { - IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - - TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName); - if (This->baseTexture.textureName != 0) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.srgbTextureName); - LEAVE_GL(); - } - + basetexture_unload(iface); resource_cleanup((IWineD3DResource *)iface); } @@ -62,11 +74,17 @@ void basetexture_unload(IWineD3DBaseTexture *iface) IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; if(This->baseTexture.textureName) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glDeleteTextures(1, &This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.srgbTextureName); This->baseTexture.textureName = 0; + LEAVE_GL(); + } + + if(This->baseTexture.srgbTextureName) { + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + glDeleteTextures(1, &This->baseTexture.srgbTextureName); This->baseTexture.srgbTextureName = 0; LEAVE_GL(); } @@ -74,33 +92,41 @@ void basetexture_unload(IWineD3DBaseTexture *iface) This->baseTexture.srgbDirty = TRUE; } -/* 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 basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD LODNew) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; + DWORD old = This->baseTexture.LOD; + /* The d3d9:texture test shows that SetLOD is ignored on non-managed + * textures. The call always returns 0, and GetLOD always returns 0 + */ if (This->resource.pool != WINED3DPOOL_MANAGED) { - return WINED3DERR_INVALIDCALL; + TRACE("Ignoring SetLOD on %s texture, returning 0\n", debug_d3dpool(This->resource.pool)); + return 0; } if(LODNew >= This->baseTexture.levels) LODNew = This->baseTexture.levels - 1; - This->baseTexture.LOD = LODNew; - TRACE("(%p) : set bogus LOD to %d\n", This, This->baseTexture.LOD); + if(This->baseTexture.LOD != LODNew) { + This->baseTexture.LOD = LODNew; - return This->baseTexture.LOD; + This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; + This->baseTexture.srgbstates[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; + if(This->baseTexture.bindCount) { + IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(This->baseTexture.sampler)); + } + } + + TRACE("(%p) : set LOD to %d\n", This, This->baseTexture.LOD); + + return old; } DWORD basetexture_get_lod(IWineD3DBaseTexture *iface) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - if (This->resource.pool != WINED3DPOOL_MANAGED) { - return WINED3DERR_INVALIDCALL; - } - TRACE("(%p) : returning %d\n", This, This->baseTexture.LOD); return This->baseTexture.LOD; @@ -128,7 +154,7 @@ HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DT * Or should we delay the applying until the texture is used for drawing? For now, apply * immediately. */ - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glBindTexture(textureDimensions, This->baseTexture.textureName); checkGLcall("glBindTexture"); @@ -158,12 +184,11 @@ HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DT WINED3DTEXTUREFILTERTYPE basetexture_get_autogen_filter_type(IWineD3DBaseTexture *iface) { - IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - FIXME("(%p) : stub\n", This); - if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) { - return WINED3DTEXF_NONE; - } - return This->baseTexture.filterType; + IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; + + FIXME("(%p) : stub\n", This); + + return This->baseTexture.filterType; } void basetexture_generate_mipmaps(IWineD3DBaseTexture *iface) @@ -190,6 +215,7 @@ BOOL basetexture_get_dirty(IWineD3DBaseTexture *iface) return This->baseTexture.dirty || This->baseTexture.srgbDirty; } +/* Context activation is done by the caller. */ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surface_desc) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; @@ -234,7 +260,7 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */ states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */ states[WINED3DTEXSTA_MAXMIPLEVEL] = 0; - states[WINED3DTEXSTA_MAXANISOTROPY] = 0; + states[WINED3DTEXSTA_MAXANISOTROPY] = 1; states[WINED3DTEXSTA_SRGBTEXTURE] = 0; states[WINED3DTEXSTA_ELEMENTINDEX] = 0; states[WINED3DTEXSTA_DMAPOFFSET] = 0; @@ -288,6 +314,7 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac return hr; } +/* GL locking is done by the caller */ static inline void apply_wrap(const GLint textureDimensions, const DWORD state, const GLint type, BOOL cond_np2) { GLint wrapParm; @@ -313,6 +340,7 @@ static inline void apply_wrap(const GLint textureDimensions, const DWORD state, } } +/* GL locking is done by the caller (state handler) */ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) @@ -321,6 +349,9 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, DWORD state, *states; GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); BOOL cond_np2 = IWineD3DBaseTexture_IsCondNP2(iface); + DWORD aniso; + + TRACE("iface %p, textureStates %p, samplerStates %p\n", iface, textureStates, samplerStates); if(This->baseTexture.is_srgb) { states = This->baseTexture.srgbstates; @@ -328,7 +359,7 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, states = This->baseTexture.states; } - /* ApplyStateChanges relies on the correct texture being bound and loaded. */ + /* This function relies on the correct texture being bound and loaded. */ if(samplerStates[WINED3DSAMP_ADDRESSU] != states[WINED3DTEXSTA_ADDRESSU]) { state = samplerStates[WINED3DSAMP_ADDRESSU]; @@ -364,17 +395,14 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, state = samplerStates[WINED3DSAMP_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]); - } - states[WINED3DTEXSTA_MAGFILTER] = state; } + + glValue = wined3d_gl_mag_filter(This->baseTexture.magLookup, + min(max(state, WINED3DTEXF_POINT), WINED3DTEXF_LINEAR)); + TRACE("ValueMAG=%d setting MAGFILTER to %x\n", state, glValue); + glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue); + + states[WINED3DTEXSTA_MAGFILTER] = state; } if((samplerStates[WINED3DSAMP_MINFILTER] != states[WINED3DTEXSTA_MINFILTER] || @@ -386,17 +414,17 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, states[WINED3DTEXSTA_MINFILTER] = samplerStates[WINED3DSAMP_MINFILTER]; states[WINED3DTEXSTA_MAXMIPLEVEL] = samplerStates[WINED3DSAMP_MAXMIPLEVEL]; - if (states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC || - states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR) + if (states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC + || states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_ANISOTROPIC) { FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d D3DSAMP_MIPFILTER value %d\n", states[WINED3DTEXSTA_MINFILTER], states[WINED3DTEXSTA_MIPFILTER]); } - glValue = This->baseTexture.minMipLookup - [min(max(samplerStates[WINED3DSAMP_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)] - .mip[min(max(samplerStates[WINED3DSAMP_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)]; + glValue = wined3d_gl_min_mip_filter(This->baseTexture.minMipLookup, + min(max(samplerStates[WINED3DSAMP_MINFILTER], WINED3DTEXF_POINT), WINED3DTEXF_LINEAR), + min(max(samplerStates[WINED3DSAMP_MIPFILTER], WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)); TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", samplerStates[WINED3DSAMP_MINFILTER], @@ -406,23 +434,46 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, if(!cond_np2) { if(states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) { - glValue = 0; + glValue = This->baseTexture.LOD; } else if(states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) { glValue = This->baseTexture.levels - 1; + } else if(states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD) { + /* baseTexture.LOD is already clamped in the setter */ + glValue = This->baseTexture.LOD; } else { glValue = states[WINED3DTEXSTA_MAXMIPLEVEL]; } + /* Note that D3DSAMP_MAXMIPLEVEL specifies the biggest mipmap(default 0), while + * GL_TEXTURE_MAX_LEVEL specifies the smallest mimap used(default 1000). + * So D3DSAMP_MAXMIPLEVEL is the same as GL_TEXTURE_BASE_LEVEL. + */ glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue); } } - if(samplerStates[WINED3DSAMP_MAXANISOTROPY] != states[WINED3DTEXSTA_MAXANISOTROPY]) { - 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 { - WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n"); + if ((states[WINED3DSAMP_MAGFILTER] != WINED3DTEXF_ANISOTROPIC + && states[WINED3DSAMP_MINFILTER] != WINED3DTEXF_ANISOTROPIC + && states[WINED3DSAMP_MIPFILTER] != WINED3DTEXF_ANISOTROPIC) + || cond_np2) + { + aniso = 1; + } + else + { + aniso = samplerStates[WINED3DSAMP_MAXANISOTROPY]; + } + + if (states[WINED3DTEXSTA_MAXANISOTROPY] != aniso) + { + if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) + { + glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); + checkGLcall("glTexParameteri(GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso)"); } - states[WINED3DTEXSTA_MAXANISOTROPY] = samplerStates[WINED3DSAMP_MAXANISOTROPY]; + else + { + WARN("Anisotropic filtering not supported.\n"); + } + states[WINED3DTEXSTA_MAXANISOTROPY] = aniso; } } diff --git a/reactos/dll/directx/wine/wined3d/buffer.c b/reactos/dll/directx/wine/wined3d/buffer.c index 666de8eadc1..104f572106d 100644 --- a/reactos/dll/directx/wine/wined3d/buffer.c +++ b/reactos/dll/directx/wine/wined3d/buffer.c @@ -34,16 +34,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); #define VB_MAXDECLCHANGES 100 /* After that number we stop converting */ #define VB_RESETDECLCHANGE 1000 /* Reset the changecount after that number of draws */ +/* Context activation is done by the caller. */ static void buffer_create_buffer_object(struct wined3d_buffer *This) { GLenum error, gl_usage; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", This, debug_d3dusage(This->resource.usage)); - /* 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 @@ -200,17 +198,20 @@ static BOOL buffer_process_converted_attribute(struct wined3d_buffer *This, return ret; } -static BOOL buffer_check_attribute(struct wined3d_buffer *This, - const struct wined3d_stream_info_element *attrib, const BOOL check_d3dcolor, const BOOL is_ffp_position, - const BOOL is_ffp_color, DWORD *stride_this_run, BOOL *float16_used) +static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct wined3d_stream_info *si, + UINT attrib_idx, const BOOL check_d3dcolor, const BOOL is_ffp_position, const BOOL is_ffp_color, + DWORD *stride_this_run, BOOL *float16_used) { + const struct wined3d_stream_info_element *attrib = &si->elements[attrib_idx]; BOOL ret = FALSE; WINED3DFORMAT format; /* 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->buffer_object != This->buffer_object) return FALSE; + if (!(si->use_map & (1 << attrib_idx)) + || attrib->buffer_object != This->buffer_object) + return FALSE; format = attrib->format_desc->format; /* Look for newly appeared conversion */ @@ -257,7 +258,7 @@ static UINT *find_conversion_shift(struct wined3d_buffer *This, { WINED3DFORMAT format; - if (strided->elements[i].buffer_object != This->buffer_object) continue; + if (!(strided->use_map & (1 << i)) || strided->elements[i].buffer_object != This->buffer_object) continue; format = strided->elements[i].format_desc->format; if (format == WINED3DFMT_R16G16_FLOAT) @@ -308,6 +309,7 @@ static UINT *find_conversion_shift(struct wined3d_buffer *This, static BOOL buffer_find_decl(struct wined3d_buffer *This) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + const struct wined3d_stream_info *si = &device->strided_streams; UINT stride_this_run = 0; BOOL float16_used = FALSE; BOOL ret = FALSE; @@ -395,8 +397,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This) } for (i = 0; i < MAX_ATTRIBS; ++i) { - ret = buffer_check_attribute(This, &device->strided_streams.elements[i], - FALSE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; + ret = buffer_check_attribute(This, si, i, FALSE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; } /* Recalculate the conversion shift map if the declaration has changed, @@ -405,7 +406,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This) if (ret && (float16_used || This->conversion_map)) { HeapFree(GetProcessHeap(), 0, This->conversion_shift); - This->conversion_shift = find_conversion_shift(This, &device->strided_streams, This->stride); + This->conversion_shift = find_conversion_shift(This, si, This->stride); } } else @@ -415,29 +416,29 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This) * the attributes that our current fixed function pipeline implementation cares for. */ BOOL support_d3dcolor = GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA); - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_POSITION], + ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION, TRUE, TRUE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_NORMAL], + ret = buffer_check_attribute(This, si, WINED3D_FFP_NORMAL, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_DIFFUSE], + ret = buffer_check_attribute(This, si, WINED3D_FFP_DIFFUSE, !support_d3dcolor, FALSE, TRUE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_SPECULAR], + ret = buffer_check_attribute(This, si, WINED3D_FFP_SPECULAR, !support_d3dcolor, FALSE, TRUE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD0], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD0, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD1], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD1, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD2], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD2, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD3], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD3, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD4], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD4, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD5], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD5, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD6], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD6, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; - ret = buffer_check_attribute(This, &device->strided_streams.elements[WINED3D_FFP_TEXCOORD7], + ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD7, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret; if (float16_used) FIXME("Float16 conversion used with fixed function vertex processing\n"); @@ -457,6 +458,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This) return ret; } +/* Context activation is done by the caller. */ static void buffer_check_buffer_object_size(struct wined3d_buffer *This) { UINT size = This->conversion_stride ? @@ -506,29 +508,18 @@ static inline void fixup_d3dcolor(DWORD *dst_color) static inline void fixup_transformed_pos(float *p) { - float x, y, z, w; - - /* rhw conversion like in drawStridedSlow */ - if (p[3] == 1.0 || ((p[3] < eps) && (p[3] > -eps))) + /* rhw conversion like in position_float4(). */ + if (p[3] != 1.0f && p[3] != 0.0f) { - x = p[0]; - y = p[1]; - z = p[2]; - w = 1.0; + float w = 1.0f / p[3]; + p[0] *= w; + p[1] *= w; + p[2] *= w; + p[3] = w; } - 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; } +/* Context activation is done by the caller. */ const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer_object) { struct wined3d_buffer *This = (struct wined3d_buffer *)iface; @@ -588,7 +579,8 @@ static ULONG STDMETHODCALLTYPE buffer_AddRef(IWineD3DBuffer *iface) return refcount; } -const BYTE *buffer_get_sysmem(struct wined3d_buffer *This) +/* Context activation is done by the caller. */ +BYTE *buffer_get_sysmem(struct wined3d_buffer *This) { /* AllocatedMemory exists if the buffer is double buffered or has no buffer object at all */ if(This->resource.allocatedMemory) return This->resource.allocatedMemory; @@ -614,7 +606,7 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); /* Download the buffer, but don't permanently enable double buffering */ if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) @@ -701,6 +693,8 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) TRACE("iface %p\n", iface); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!This->buffer_object) { /* TODO: Make converting independent from VBOs */ @@ -736,7 +730,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) if (This->conversion_count > VB_MAXDECLCHANGES) { FIXME("Too many declaration changes, stopping converting\n"); - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); checkGLcall("glDeleteBuffersARB"); @@ -809,7 +803,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) if (!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); } ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); @@ -959,7 +953,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER); } - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); @@ -985,6 +979,16 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface) TRACE("(%p)\n", This); + /* In the case that the number of Unmap calls > the + * number of Map calls, d3d returns always D3D_OK. + * This is also needed to prevent Map from returning garbage on + * the next call (this will happen if the lock_count is < 0). */ + if(This->lock_count == 0) + { + TRACE("Unmap called without a previous Map call!\n"); + return WINED3D_OK; + } + if (InterlockedDecrement(&This->lock_count)) { /* Delay loading the buffer until everything is unlocked */ @@ -1001,7 +1005,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface) IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER); } - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); diff --git a/reactos/dll/directx/wine/wined3d/context.c b/reactos/dll/directx/wine/wined3d/context.c index 2c6703f3603..c4cd43659f5 100644 --- a/reactos/dll/directx/wine/wined3d/context.c +++ b/reactos/dll/directx/wine/wined3d/context.c @@ -2,6 +2,7 @@ * Context and render target management in wined3d * * Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * Copyright 2009 Henri Verbeet for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,38 +28,66 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->adapter->gl_info +#define GLINFO_LOCATION (*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; +static DWORD wined3d_context_tls_idx; /* FBO helper functions */ -void context_bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) +/* GL locking is done by the caller */ +void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo) { - const IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint f; - if (!*fbo) + if (!fbo) { - GL_EXTCALL(glGenFramebuffersEXT(1, fbo)); - checkGLcall("glGenFramebuffersEXT()"); - TRACE("Created FBO %d\n", *fbo); + f = 0; + } + else + { + if (!*fbo) + { + GL_EXTCALL(glGenFramebuffersEXT(1, fbo)); + checkGLcall("glGenFramebuffersEXT()"); + TRACE("Created FBO %u.\n", *fbo); + } + f = *fbo; } - GL_EXTCALL(glBindFramebufferEXT(target, *fbo)); + switch (target) + { + case GL_READ_FRAMEBUFFER_EXT: + if (context->fbo_read_binding == f) return; + context->fbo_read_binding = f; + break; + + case GL_DRAW_FRAMEBUFFER_EXT: + if (context->fbo_draw_binding == f) return; + context->fbo_draw_binding = f; + break; + + case GL_FRAMEBUFFER_EXT: + if (context->fbo_read_binding == f + && context->fbo_draw_binding == f) return; + context->fbo_read_binding = f; + context->fbo_draw_binding = f; + break; + + default: + FIXME("Unhandled target %#x.\n", target); + break; + } + + GL_EXTCALL(glBindFramebufferEXT(target, f)); checkGLcall("glBindFramebuffer()"); } -static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) +/* GL locking is done by the caller */ +static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info) { unsigned int i; - 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)); @@ -66,16 +95,29 @@ static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) } 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(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2D()"); +} + +/* GL locking is done by the caller */ +static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, fbo); + context_clean_fbo_attachments(gl_info); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); + GL_EXTCALL(glDeleteFramebuffersEXT(1, fbo)); checkGLcall("glDeleteFramebuffers()"); } -static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD3DSurface *surface, BOOL force_preload) +/* GL locking is done by the caller */ +static void context_apply_attachment_filter_states(IWineD3DSurface *surface, BOOL force_preload) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; + IWineD3DDeviceImpl *device = surface_impl->resource.wineD3DDevice; IWineD3DBaseTextureImpl *texture_impl; BOOL update_minfilter = FALSE; BOOL update_magfilter = FALSE; @@ -100,7 +142,7 @@ static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD 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)); + IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(texture_impl->baseTexture.sampler)); } IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl); @@ -111,7 +153,7 @@ static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD GLenum target, bind_target; GLint old_binding; - target = surface_impl->glDescription.target; + target = surface_impl->texture_target; if (target == GL_TEXTURE_2D) { bind_target = GL_TEXTURE_2D; @@ -126,7 +168,7 @@ static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD surface_internal_preload(surface, SRGB_RGB); - glBindTexture(bind_target, surface_impl->glDescription.textureName); + glBindTexture(bind_target, surface_impl->texture_name); if (update_minfilter) glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); if (update_magfilter) glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(bind_target, old_binding); @@ -135,44 +177,93 @@ static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD 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) +/* GL locking is done by the caller */ +void context_attach_depth_stencil_fbo(struct wined3d_context *context, + GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) { IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil; + const struct wined3d_gl_info *gl_info = context->gl_info; TRACE("Attach depth stencil %p\n", depth_stencil); if (depth_stencil) { + DWORD format_flags = depth_stencil_impl->resource.format_desc->Flags; + 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); + if (format_flags & WINED3DFMT_FLAG_DEPTH) + { + GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id)); + checkGLcall("glFramebufferRenderbufferEXT()"); + } - GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, depth_stencil_impl->glDescription.target, - depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level)); + if (format_flags & WINED3DFMT_FLAG_STENCIL) + { + GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id)); + checkGLcall("glFramebufferRenderbufferEXT()"); + } + } + else + { + context_apply_attachment_filter_states(depth_stencil, TRUE); + + if (format_flags & WINED3DFMT_FLAG_DEPTH) + { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, + depth_stencil_impl->texture_target, depth_stencil_impl->texture_name, + depth_stencil_impl->texture_level)); + checkGLcall("glFramebufferTexture2DEXT()"); + } + + if (format_flags & WINED3DFMT_FLAG_STENCIL) + { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_STENCIL_ATTACHMENT_EXT, + depth_stencil_impl->texture_target, depth_stencil_impl->texture_name, + depth_stencil_impl->texture_level)); + checkGLcall("glFramebufferTexture2DEXT()"); + } + } + + if (!(format_flags & WINED3DFMT_FLAG_DEPTH)) + { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); checkGLcall("glFramebufferTexture2DEXT()"); } - } else { + + if (!(format_flags & WINED3DFMT_FLAG_STENCIL)) + { + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2DEXT()"); + } + } + else + { GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); checkGLcall("glFramebufferTexture2DEXT()"); + + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); + checkGLcall("glFramebufferTexture2DEXT()"); } } -void context_attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) +/* GL locking is done by the caller */ +void context_attach_surface_fbo(const struct wined3d_context *context, + GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) { const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface; + const struct wined3d_gl_info *gl_info = context->gl_info; TRACE("Attach surface %p to %u\n", surface, idx); if (surface) { - context_apply_attachment_filter_states((IWineD3DDevice *)This, surface, TRUE); + context_apply_attachment_filter_states(surface, TRUE); - GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, surface_impl->glDescription.target, - surface_impl->glDescription.textureName, surface_impl->glDescription.level)); + GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, surface_impl->texture_target, + surface_impl->texture_name, surface_impl->texture_level)); checkGLcall("glFramebufferTexture2DEXT()"); } else { GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0)); @@ -180,9 +271,10 @@ void context_attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWO } } -static void context_check_fbo_status(IWineD3DDevice *iface) +/* GL locking is done by the caller */ +static void context_check_fbo_status(struct wined3d_context *context) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct wined3d_gl_info *gl_info = context->gl_info; GLenum status; status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); @@ -197,7 +289,7 @@ static void context_check_fbo_status(IWineD3DDevice *iface) /* Dump the FBO attachments */ for (i = 0; i < GL_LIMITS(buffers); ++i) { - attachment = (IWineD3DSurfaceImpl *)This->activeContext->current_fbo->render_targets[i]; + attachment = (IWineD3DSurfaceImpl *)context->current_fbo->render_targets[i]; if (attachment) { FIXME("\tColor attachment %d: (%p) %s %ux%u\n", @@ -205,7 +297,7 @@ static void context_check_fbo_status(IWineD3DDevice *iface) attachment->pow2Width, attachment->pow2Height); } } - attachment = (IWineD3DSurfaceImpl *)This->activeContext->current_fbo->depth_stencil; + attachment = (IWineD3DSurfaceImpl *)context->current_fbo->depth_stencil; if (attachment) { FIXME("\tDepth attachment: (%p) %s %ux%u\n", @@ -215,113 +307,270 @@ static void context_check_fbo_status(IWineD3DDevice *iface) } } -static struct fbo_entry *context_create_fbo_entry(IWineD3DDevice *iface) +static struct fbo_entry *context_create_fbo_entry(struct wined3d_context *context) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); entry->render_targets = HeapAlloc(GetProcessHeap(), 0, GL_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; + memcpy(entry->render_targets, device->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)); + entry->depth_stencil = device->stencilBufferTarget; entry->attached = FALSE; entry->id = 0; return entry; } -static void context_destroy_fbo_entry(IWineD3DDeviceImpl *This, struct fbo_entry *entry) +/* GL locking is done by the caller */ +static void context_reuse_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry) +{ + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; + + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &entry->id); + context_clean_fbo_attachments(gl_info); + + memcpy(entry->render_targets, device->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)); + entry->depth_stencil = device->stencilBufferTarget; + entry->attached = FALSE; +} + +/* GL locking is done by the caller */ +static void context_destroy_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry) { if (entry->id) { TRACE("Destroy FBO %d\n", entry->id); - context_destroy_fbo(This, &entry->id); + context_destroy_fbo(context, &entry->id); } + --context->fbo_entry_count; 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) +/* GL locking is done by the caller */ +static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry; LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry) { - if (!memcmp(entry->render_targets, This->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)) - && entry->depth_stencil == This->stencilBufferTarget) + if (!memcmp(entry->render_targets, device->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)) + && entry->depth_stencil == device->stencilBufferTarget) { + list_remove(&entry->entry); + list_add_head(&context->fbo_list, &entry->entry); return entry; } } - entry = context_create_fbo_entry(iface); - list_add_head(&context->fbo_list, &entry->entry); + if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES) + { + entry = context_create_fbo_entry(context); + list_add_head(&context->fbo_list, &entry->entry); + ++context->fbo_entry_count; + } + else + { + entry = LIST_ENTRY(list_tail(&context->fbo_list), struct fbo_entry, entry); + context_reuse_fbo_entry(context, entry); + list_remove(&entry->entry); + list_add_head(&context->fbo_list, &entry->entry); + } + return entry; } -static void context_apply_fbo_entry(IWineD3DDevice *iface, struct fbo_entry *entry) +/* GL locking is done by the caller */ +static void context_apply_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int i; - context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &entry->id); + context_bind_fbo(context, 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); + IWineD3DSurface *render_target = device->render_targets[i]; + context_attach_surface_fbo(context, 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; + if (device->stencilBufferTarget) + { + unsigned int w = ((IWineD3DSurfaceImpl *)device->render_targets[0])->pow2Width; + unsigned int h = ((IWineD3DSurfaceImpl *)device->render_targets[0])->pow2Height; - surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h); + surface_set_compatible_renderbuffer(device->stencilBufferTarget, w, h); } - context_attach_depth_stencil_fbo(This, GL_FRAMEBUFFER_EXT, This->stencilBufferTarget, TRUE); + context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, device->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 (device->render_targets[i]) + context_apply_attachment_filter_states(device->render_targets[i], FALSE); } - if (This->stencilBufferTarget) - context_apply_attachment_filter_states(iface, This->stencilBufferTarget, FALSE); + if (device->stencilBufferTarget) + context_apply_attachment_filter_states(device->stencilBufferTarget, FALSE); } for (i = 0; i < GL_LIMITS(buffers); ++i) { - if (This->render_targets[i]) - This->draw_buffers[i] = GL_COLOR_ATTACHMENT0_EXT + i; + if (device->render_targets[i]) + device->draw_buffers[i] = GL_COLOR_ATTACHMENT0_EXT + i; else - This->draw_buffers[i] = GL_NONE; + device->draw_buffers[i] = GL_NONE; } } -static void context_apply_fbo_state(IWineD3DDevice *iface) +/* GL locking is done by the caller */ +static void context_apply_fbo_state(struct wined3d_context *context) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - WineD3DContext *context = This->activeContext; - - if (This->render_offscreen) + if (context->render_offscreen) { - context->current_fbo = context_find_fbo_entry(iface, context); - context_apply_fbo_entry(iface, context->current_fbo); + context->current_fbo = context_find_fbo_entry(context); + context_apply_fbo_entry(context, context->current_fbo); } else { context->current_fbo = NULL; - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); } - context_check_fbo_status(iface); + context_check_fbo_status(context); +} + +/* Context activation is done by the caller. */ +void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (context->free_occlusion_query_count) + { + query->id = context->free_occlusion_queries[--context->free_occlusion_query_count]; + } + else + { + if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) + { + ENTER_GL(); + GL_EXTCALL(glGenQueriesARB(1, &query->id)); + checkGLcall("glGenQueriesARB"); + LEAVE_GL(); + + TRACE("Allocated occlusion query %u in context %p.\n", query->id, context); + } + else + { + WARN("Occlusion queries not supported, not allocating query id.\n"); + query->id = 0; + } + } + + query->context = context; + list_add_head(&context->occlusion_queries, &query->entry); +} + +void context_free_occlusion_query(struct wined3d_occlusion_query *query) +{ + struct wined3d_context *context = query->context; + + list_remove(&query->entry); + query->context = NULL; + + if (context->free_occlusion_query_count >= context->free_occlusion_query_size - 1) + { + UINT new_size = context->free_occlusion_query_size << 1; + GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_occlusion_queries, + new_size * sizeof(*context->free_occlusion_queries)); + + if (!new_data) + { + ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context); + return; + } + + context->free_occlusion_query_size = new_size; + context->free_occlusion_queries = new_data; + } + + context->free_occlusion_queries[context->free_occlusion_query_count++] = query->id; +} + +/* Context activation is done by the caller. */ +void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (context->free_event_query_count) + { + query->id = context->free_event_queries[--context->free_event_query_count]; + } + else + { + if (GL_SUPPORT(APPLE_FENCE)) + { + ENTER_GL(); + GL_EXTCALL(glGenFencesAPPLE(1, &query->id)); + checkGLcall("glGenFencesAPPLE"); + LEAVE_GL(); + + TRACE("Allocated event query %u in context %p.\n", query->id, context); + } + else if(GL_SUPPORT(NV_FENCE)) + { + ENTER_GL(); + GL_EXTCALL(glGenFencesNV(1, &query->id)); + checkGLcall("glGenFencesNV"); + LEAVE_GL(); + + TRACE("Allocated event query %u in context %p.\n", query->id, context); + } + else + { + WARN("Event queries not supported, not allocating query id.\n"); + query->id = 0; + } + } + + query->context = context; + list_add_head(&context->event_queries, &query->entry); +} + +void context_free_event_query(struct wined3d_event_query *query) +{ + struct wined3d_context *context = query->context; + + list_remove(&query->entry); + query->context = NULL; + + if (context->free_event_query_count >= context->free_event_query_size - 1) + { + UINT new_size = context->free_event_query_size << 1; + GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries, + new_size * sizeof(*context->free_event_queries)); + + if (!new_data) + { + ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context); + return; + } + + context->free_event_query_size = new_size; + context->free_event_queries = new_data; + } + + context->free_event_queries[context->free_event_query_count++] = query->id; } void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type) @@ -329,15 +578,25 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; UINT i; + if (!This->d3d_initialized) return; + switch(type) { case WINED3DRTYPE_SURFACE: { + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + for (i = 0; i < This->numContexts; ++i) { + struct wined3d_context *context = This->contexts[i]; + const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry, *entry2; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->contexts[i]->fbo_list, struct fbo_entry, entry) + if (context->current_rt == (IWineD3DSurface *)resource) context->current_rt = NULL; + + ENTER_GL(); + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) { BOOL destroyed = FALSE; UINT j; @@ -346,14 +605,16 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource { if (entry->render_targets[j] == (IWineD3DSurface *)resource) { - context_destroy_fbo_entry(This, entry); + context_destroy_fbo_entry(context, entry); destroyed = TRUE; } } if (!destroyed && entry->depth_stencil == (IWineD3DSurface *)resource) - context_destroy_fbo_entry(This, entry); + context_destroy_fbo_entry(context, entry); } + + LEAVE_GL(); } break; @@ -364,6 +625,156 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource } } +static void context_destroy_gl_resources(struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_occlusion_query *occlusion_query; + struct wined3d_event_query *event_query; + struct fbo_entry *entry, *entry2; + BOOL has_glctx; + + has_glctx = pwglMakeCurrent(context->hdc, context->glCtx); + if (!has_glctx) WARN("Failed to activate context. Window already destroyed?\n"); + + ENTER_GL(); + + LIST_FOR_EACH_ENTRY(occlusion_query, &context->occlusion_queries, struct wined3d_occlusion_query, entry) + { + if (has_glctx && GL_SUPPORT(ARB_OCCLUSION_QUERY)) GL_EXTCALL(glDeleteQueriesARB(1, &occlusion_query->id)); + occlusion_query->context = NULL; + } + + LIST_FOR_EACH_ENTRY(event_query, &context->event_queries, struct wined3d_event_query, entry) + { + if (has_glctx) + { + if (GL_SUPPORT(APPLE_FENCE)) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->id)); + else if (GL_SUPPORT(NV_FENCE)) GL_EXTCALL(glDeleteFencesNV(1, &event_query->id)); + } + event_query->context = NULL; + } + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) { + if (!has_glctx) entry->id = 0; + context_destroy_fbo_entry(context, entry); + } + if (has_glctx) + { + if (context->src_fbo) + { + TRACE("Destroy src FBO %d\n", context->src_fbo); + context_destroy_fbo(context, &context->src_fbo); + } + if (context->dst_fbo) + { + TRACE("Destroy dst FBO %d\n", context->dst_fbo); + context_destroy_fbo(context, &context->dst_fbo); + } + if (context->dummy_arbfp_prog) + { + GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog)); + } + + if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) + GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries)); + + if (GL_SUPPORT(APPLE_FENCE)) + GL_EXTCALL(glDeleteFencesAPPLE(context->free_event_query_count, context->free_event_queries)); + else if (GL_SUPPORT(NV_FENCE)) + GL_EXTCALL(glDeleteFencesNV(context->free_event_query_count, context->free_event_queries)); + + checkGLcall("context cleanup"); + } + + LEAVE_GL(); + + HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, context->free_event_queries); + + if (!pwglMakeCurrent(NULL, NULL)) + { + ERR("Failed to disable GL context.\n"); + } + + if (context->isPBuffer) + { + GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc)); + GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer)); + } + else + { + ReleaseDC(context->win_handle, context->hdc); + } + + if (!pwglDeleteContext(context->glCtx)) + { + DWORD err = GetLastError(); + ERR("wglDeleteContext(%p) failed, last error %#x.\n", context->glCtx, err); + } +} + +DWORD context_get_tls_idx(void) +{ + return wined3d_context_tls_idx; +} + +void context_set_tls_idx(DWORD idx) +{ + wined3d_context_tls_idx = idx; +} + +struct wined3d_context *context_get_current(void) +{ + return TlsGetValue(wined3d_context_tls_idx); +} + +BOOL context_set_current(struct wined3d_context *ctx) +{ + struct wined3d_context *old = context_get_current(); + + if (old == ctx) + { + TRACE("Already using D3D context %p.\n", ctx); + return TRUE; + } + + if (old) + { + if (old->destroyed) + { + TRACE("Switching away from destroyed context %p.\n", old); + context_destroy_gl_resources(old); + HeapFree(GetProcessHeap(), 0, old); + } + else + { + old->current = 0; + } + } + + if (ctx) + { + TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc); + if (!pwglMakeCurrent(ctx->hdc, ctx->glCtx)) + { + ERR("Failed to make GL context %p current on device context %p.\n", ctx->glCtx, ctx->hdc); + return FALSE; + } + ctx->current = 1; + } + else + { + TRACE("Clearing current D3D context.\n"); + if (!pwglMakeCurrent(NULL, NULL)) + { + ERR("Failed to clear current GL context.\n"); + return FALSE; + } + } + + return TlsSetValue(wined3d_context_tls_idx, ctx); +} + /***************************************************************************** * Context_MarkStateDirty * @@ -377,12 +788,13 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource * StateTable: Pointer to the state table in use(for state grouping) * *****************************************************************************/ -static void Context_MarkStateDirty(WineD3DContext *context, DWORD state, const struct StateEntry *StateTable) { +static void Context_MarkStateDirty(struct wined3d_context *context, DWORD state, const struct StateEntry *StateTable) +{ DWORD rep = StateTable[state].representative; DWORD idx; BYTE shift; - if(!rep || isStateDirty(context, rep)) return; + if (isStateDirty(context, rep)) return; context->dirtyArray[context->numDirtyEntries++] = rep; idx = rep >> 5; @@ -406,8 +818,10 @@ static void Context_MarkStateDirty(WineD3DContext *context, DWORD state, const s * pbuffer: optional pbuffer used with this context * *****************************************************************************/ -static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_handle, HDC hdc, HGLRC glCtx, HPBUFFERARB pbuffer) { - WineD3DContext **oldArray = This->contexts; +static struct wined3d_context *AddContextToArray(IWineD3DDeviceImpl *This, + HWND win_handle, HDC hdc, HGLRC glCtx, HPBUFFERARB pbuffer) +{ + struct wined3d_context **oldArray = This->contexts; DWORD state; This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * (This->numContexts + 1)); @@ -420,7 +834,7 @@ static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_hand memcpy(This->contexts, oldArray, sizeof(*This->contexts) * This->numContexts); } - This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineD3DContext)); + This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**This->contexts)); if(This->contexts[This->numContexts] == NULL) { ERR("Unable to allocate a new context\n"); HeapFree(GetProcessHeap(), 0, This->contexts); @@ -437,7 +851,8 @@ 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, This->StateTable); + if (This->StateTable[state].representative) + Context_MarkStateDirty(This->contexts[This->numContexts], state, This->StateTable); } This->numContexts++; @@ -636,12 +1051,15 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, * pPresentParameters: contains the pixelformats to use for onscreen rendering * *****************************************************************************/ -WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win_handle, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms) { - HDC oldDrawable, hdc; +struct wined3d_context *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, + HWND win_handle, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms) +{ + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + struct wined3d_context *ret = NULL; HPBUFFERARB pbuffer = NULL; - HGLRC ctx = NULL, oldCtx; - WineD3DContext *ret = NULL; unsigned int s; + HGLRC ctx; + HDC hdc; TRACE("(%p): Creating a %s context for render target %p\n", This, create_pbuffer ? "offscreen" : "onscreen", target); @@ -757,7 +1175,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar /* 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; + return NULL; } DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd); @@ -776,7 +1194,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar if(!res) { ERR("wglSetPixelFormatWINE failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); - return FALSE; + return NULL; } } else if(oldPixelFormat) { /* OpenGL doesn't allow pixel format adjustments. Print an error and continue using the old format. @@ -784,13 +1202,21 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar ERR("HDC=%p is already set to iPixelFormat=%d and OpenGL doesn't allow changes!\n", hdc, oldPixelFormat); } else { ERR("SetPixelFormat failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat); - return FALSE; + return NULL; } } } ctx = pwglCreateContext(hdc); - if(This->numContexts) pwglShareLists(This->contexts[0]->glCtx, ctx); + if (This->numContexts) + { + if (!pwglShareLists(This->contexts[0]->glCtx, ctx)) + { + DWORD err = GetLastError(); + ERR("wglShareLists(%p, %p) failed, last error %#x.\n", + This->contexts[0]->glCtx, ctx, err); + } + } if(!ctx) { ERR("Failed to create a WGL context\n"); @@ -803,14 +1229,20 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar ret = AddContextToArray(This, win_handle, hdc, ctx, pbuffer); if(!ret) { ERR("Failed to add the newly created context to the context list\n"); - pwglDeleteContext(ctx); + if (!pwglDeleteContext(ctx)) + { + DWORD err = GetLastError(); + ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, err); + } if(create_pbuffer) { GL_EXTCALL(wglReleasePbufferDCARB(pbuffer, hdc)); GL_EXTCALL(wglDestroyPbufferARB(pbuffer)); } goto out; } + ret->gl_info = &This->adapter->gl_info; ret->surface = (IWineD3DSurface *) target; + ret->current_rt = (IWineD3DSurface *)target; ret->isPBuffer = create_pbuffer; ret->tid = GetCurrentThreadId(); if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) { @@ -825,18 +1257,27 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); } + ret->free_occlusion_query_size = 4; + ret->free_occlusion_queries = HeapAlloc(GetProcessHeap(), 0, + ret->free_occlusion_query_size * sizeof(*ret->free_occlusion_queries)); + if (!ret->free_occlusion_queries) goto out; + + list_init(&ret->occlusion_queries); + + ret->free_event_query_size = 4; + ret->free_event_queries = HeapAlloc(GetProcessHeap(), 0, + ret->free_event_query_size * sizeof(*ret->free_event_queries)); + if (!ret->free_event_queries) goto out; + + list_init(&ret->event_queries); + 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) { + if (!context_set_current(ret)) + { ERR("Cannot activate context to set up defaults\n"); goto out; } @@ -847,7 +1288,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar TRACE("Setting up the screen\n"); /* Clear the screen */ - glClearColor(1.0, 0.0, 0.0, 0.0); + glClearColor(1.0f, 0.0f, 0.0f, 0.0f); checkGLcall("glClearColor"); glClearIndex(0); glClearDepth(1); @@ -891,30 +1332,54 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar for(s = 1; s < GL_LIMITS(textures); s++) { GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s)); glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1); - checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...\n"); + checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ..."); } } + if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + /* MacOS(radeon X1600 at least, but most likely others too) refuses to draw if GLSL and ARBFP are + * enabled, but the currently bound arbfp program is 0. Enabling ARBFP with prog 0 is invalid, but + * GLSL should bypass this. This causes problems in programs that never use the fixed function pipeline, + * because the ARBFP extension is enabled by the ARBFP pipeline at context creation, but no program + * is ever assigned. + * + * So make sure a program is assigned to each context. The first real ARBFP use will set a different + * program and the dummy program is destroyed when the context is destroyed. + */ + const char *dummy_program = + "!!ARBfp1.0\n" + "MOV result.color, fragment.color.primary;\n" + "END\n"; + GL_EXTCALL(glGenProgramsARB(1, &ret->dummy_arbfp_prog)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret->dummy_arbfp_prog)); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program)); + } for(s = 0; s < GL_LIMITS(point_sprite_units); s++) { GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s)); glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); - checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"); + checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)"); } + + if (GL_SUPPORT(EXT_PROVOKING_VERTEX)) + { + GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT)); + } + 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: + if (ret) + { + HeapFree(GetProcessHeap(), 0, ret->free_event_queries); + HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty); + HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty); + HeapFree(GetProcessHeap(), 0, ret); + } return NULL; } @@ -932,8 +1397,9 @@ out: * context: Context to remove * *****************************************************************************/ -static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *context) { - WineD3DContext **new_array; +static void RemoveContextFromArray(IWineD3DDeviceImpl *This, struct wined3d_context *context) +{ + struct wined3d_context **new_array; BOOL found = FALSE; UINT i; @@ -943,7 +1409,6 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con { if (This->contexts[i] == context) { - HeapFree(GetProcessHeap(), 0, context); found = TRUE; break; } @@ -989,52 +1454,35 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con * context: Context to destroy * *****************************************************************************/ -void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) { - struct fbo_entry *entry, *entry2; +void DestroyContext(IWineD3DDeviceImpl *This, struct wined3d_context *context) +{ + BOOL destroy; TRACE("Destroying ctx %p\n", context); - /* 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(); - - if (This->activeContext == context) + if (context->tid == GetCurrentThreadId() || !context->current) { - This->activeContext = NULL; - TRACE("Destroying the active context.\n"); - } + context_destroy_gl_resources(context); + destroy = TRUE; - /* 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); + if (!context_set_current(NULL)) + { + ERR("Failed to clear current D3D context.\n"); + } + } + else + { + context->destroyed = 1; + destroy = FALSE; + } HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty); HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty); RemoveContextFromArray(This, context); + if (destroy) HeapFree(GetProcessHeap(), 0, context); } +/* GL locking is done by the caller */ static inline void set_blit_dimension(UINT width, UINT height) { glMatrixMode(GL_PROJECTION); checkGLcall("glMatrixMode(GL_PROJECTION)"); @@ -1064,14 +1512,20 @@ static inline void set_blit_dimension(UINT width, UINT height) { * height: render target height * *****************************************************************************/ -static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *context, UINT width, UINT height) { - int i, sampler; +/* Context activation is done by the caller. */ +static inline void SetupForBlit(IWineD3DDeviceImpl *This, struct wined3d_context *context, UINT width, UINT height) +{ + int i; const struct StateEntry *StateTable = This->StateTable; + const struct wined3d_gl_info *gl_info = context->gl_info; + DWORD sampler; TRACE("Setting up context %p for blitting\n", context); if(context->last_was_blit) { if(context->blit_w != width || context->blit_h != height) { + ENTER_GL(); set_blit_dimension(width, height); + LEAVE_GL(); 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 @@ -1086,7 +1540,10 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex /* TODO: Use a display list */ /* Disable shaders */ - This->shader_backend->shader_select((IWineD3DDevice *)This, FALSE, FALSE); + ENTER_GL(); + This->shader_backend->shader_select(context, FALSE, FALSE); + LEAVE_GL(); + Context_MarkStateDirty(context, STATE_VSHADER, StateTable); Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable); @@ -1124,7 +1581,8 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);"); - if (sampler != -1) { + if (sampler != WINED3D_UNMAPPED_STAGE) + { if (sampler < MAX_TEXTURES) { Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable); } @@ -1159,11 +1617,12 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) { glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, - 0.0); + 0.0f); checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ..."); } - if (sampler != -1) { + if (sampler != WINED3D_UNMAPPED_STAGE) + { if (sampler < MAX_TEXTURES) { Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + sampler), StateTable); Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable); @@ -1203,7 +1662,7 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex } glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); checkGLcall("glColorMask"); - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable); + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE), StateTable); if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { glDisable(GL_COLOR_SUM_EXT); Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE), StateTable); @@ -1227,9 +1686,11 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex 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), StateTable); - LEAVE_GL(); set_blit_dimension(width, height); + + LEAVE_GL(); + context->blit_w = width; context->blit_h = height; Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable); Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable); @@ -1245,7 +1706,8 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex * If none can be found the swapchain is requested to create a new context * *****************************************************************************/ -static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchain, DWORD tid) { +static struct wined3d_context *findThreadContextForSwapChain(IWineD3DSwapChain *swapchain, DWORD tid) +{ unsigned int i; for(i = 0; i < ((IWineD3DSwapChainImpl *) swapchain)->num_contexts; i++) { @@ -1271,26 +1733,35 @@ static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchai * Returns: The needed context * *****************************************************************************/ -static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid) { +static inline struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid) +{ IWineD3DSwapChain *swapchain = NULL; - BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen; - WineD3DContext *context = This->activeContext; - BOOL oldRenderOffscreen = This->render_offscreen; - const struct GlPixelFormatDesc *old = ((IWineD3DSurfaceImpl *)This->lastActiveRenderTarget)->resource.format_desc; - const struct GlPixelFormatDesc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc; + struct wined3d_context *current_context = context_get_current(); const struct StateEntry *StateTable = This->StateTable; + struct wined3d_context *context; + BOOL old_render_offscreen; - /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers - * the alpha blend state changes with different render target formats - */ - if (old->format != new->format) + if (current_context && current_context->destroyed) current_context = NULL; + + if (!target) { - /* Disable blending when the alpha mask has changed and when a format doesn't support blending */ - if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask) - || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) + if (current_context + && current_context->current_rt + && ((IWineD3DSurfaceImpl *)current_context->surface)->resource.wineD3DDevice == This) { - Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + target = current_context->current_rt; } + else + { + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)This->swapchains[0]; + if (swapchain->backBuffer) target = swapchain->backBuffer[0]; + else target = swapchain->frontBuffer; + } + } + + if (current_context && current_context->current_rt == target) + { + return current_context; } if (SUCCEEDED(IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain))) { @@ -1298,7 +1769,8 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf context = findThreadContextForSwapChain(swapchain, tid); - This->render_offscreen = FALSE; + old_render_offscreen = context->render_offscreen; + context->render_offscreen = FALSE; /* The context != This->activeContext will catch a NOP context change. This can occur * if we are switching back to swapchain rendering in case of FBO or Back Buffer offscreen * rendering. No context change is needed in that case @@ -1310,157 +1782,161 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf } } IWineD3DSwapChain_Release(swapchain); - - if(oldRenderOffscreen) { - 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 { + } + else + { TRACE("Rendering offscreen\n"); - This->render_offscreen = TRUE; - switch(wined3d_settings.offscreen_rendering_mode) { - case ORM_FBO: - /* FBOs do not need a different context. Stay with whatever context is active at the moment */ - if(This->activeContext && tid == This->lastThread) { - context = This->activeContext; - } else { - /* This may happen if the app jumps straight into offscreen rendering - * Start using the context of the primary swapchain. tid == 0 is no problem - * for findThreadContextForSwapChain. - * - * Can also happen on thread switches - in that case findThreadContextForSwapChain - * is perfect to call. - */ - context = findThreadContextForSwapChain(This->swapchains[0], tid); - } - break; - - case ORM_PBUFFER: +retry: + if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) + { + IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *)target; + if (!This->pbufferContext + || This->pbufferWidth < targetimpl->currentDesc.Width + || This->pbufferHeight < targetimpl->currentDesc.Height) { - IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *) target; - if(This->pbufferContext == NULL || - This->pbufferWidth < targetimpl->currentDesc.Width || - This->pbufferHeight < targetimpl->currentDesc.Height) { - if(This->pbufferContext) { - DestroyContext(This, This->pbufferContext); - } + if (This->pbufferContext) DestroyContext(This, This->pbufferContext); - /* The display is irrelevant here, the window is 0. But CreateContext needs a valid X connection. - * Create the context on the same server as the primary swapchain. The primary swapchain is exists at this point. - */ - This->pbufferContext = CreateContext(This, targetimpl, - ((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0]->win_handle, - TRUE /* pbuffer */, &((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms); - This->pbufferWidth = targetimpl->currentDesc.Width; - This->pbufferHeight = targetimpl->currentDesc.Height; - } - - if(This->pbufferContext) { - if(This->pbufferContext->tid != 0 && This->pbufferContext->tid != tid) { - FIXME("The PBuffr context is only supported for one thread for now!\n"); - } - This->pbufferContext->tid = tid; - context = This->pbufferContext; - break; - } else { - ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering\n"); - wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; - } + /* The display is irrelevant here, the window is 0. But + * CreateContext needs a valid X connection. Create the context + * on the same server as the primary swapchain. The primary + * swapchain is exists at this point. */ + This->pbufferContext = CreateContext(This, targetimpl, + ((IWineD3DSwapChainImpl *)This->swapchains[0])->context[0]->win_handle, + TRUE /* pbuffer */, &((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms); + This->pbufferWidth = targetimpl->currentDesc.Width; + This->pbufferHeight = targetimpl->currentDesc.Height; } - case ORM_BACKBUFFER: - /* Stay with the currently active context for back buffer rendering */ - if(This->activeContext && tid == This->lastThread) { - context = This->activeContext; - } else { - /* This may happen if the app jumps straight into offscreen rendering - * Start using the context of the primary swapchain. tid == 0 is no problem - * for findThreadContextForSwapChain. - * - * Can also happen on thread switches - in that case findThreadContextForSwapChain - * is perfect to call. - */ - context = findThreadContextForSwapChain(This->swapchains[0], tid); + if (This->pbufferContext) + { + if (This->pbufferContext->tid && This->pbufferContext->tid != tid) + { + FIXME("The PBuffer context is only supported for one thread for now!\n"); } - break; + This->pbufferContext->tid = tid; + context = This->pbufferContext; + } + else + { + ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering.\n"); + wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; + goto retry; + } + } + else + { + /* Stay with the currently active context. */ + if (current_context + && ((IWineD3DSurfaceImpl *)current_context->surface)->resource.wineD3DDevice == This) + { + context = current_context; + } + else + { + /* This may happen if the app jumps straight into offscreen rendering + * Start using the context of the primary swapchain. tid == 0 is no problem + * for findThreadContextForSwapChain. + * + * Can also happen on thread switches - in that case findThreadContextForSwapChain + * is perfect to call. */ + context = findThreadContextForSwapChain(This->swapchains[0], tid); + } } - if(!oldRenderOffscreen) { - 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); + old_render_offscreen = context->render_offscreen; + context->render_offscreen = TRUE; + } + + if (context->render_offscreen != old_render_offscreen) + { + Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable); + Context_MarkStateDirty(context, STATE_VDECL, StateTable); + Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable); + Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable); + Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable); + } + + /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers + * the alpha blend state changes with different render target formats. */ + if (!context->current_rt) + { + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + } + else + { + const struct GlPixelFormatDesc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc; + const struct GlPixelFormatDesc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc; + + if (old->format != new->format) + { + /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */ + if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask) + || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) + { + Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable); + } + } + + /* When switching away from an offscreen render target, and we're not + * using FBOs, we have to read the drawable into the texture. This is + * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There + * are some things that need care though. PreLoad needs a GL context, + * and FindContext is called before the context is activated. It also + * has to be called with the old rendertarget active, otherwise a + * wrong drawable is read. */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO + && old_render_offscreen && context->current_rt != target) + { + BOOL oldInDraw = This->isInDraw; + + /* surface_internal_preload() requires a context to load the + * texture, so it will call ActivateContext. Set isInDraw to true + * to signal surface_internal_preload() that it has a context. */ + + /* FIXME: This is just broken. There's no guarantee whatsoever + * that the currently active context, if any, is appropriate for + * reading back the render target. We should probably call + * context_set_current(context) here and then rely on + * ActivateContext() doing the right thing. */ + This->isInDraw = TRUE; + + /* Read the back buffer of the old drawable into the destination texture. */ + if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb) + { + surface_internal_preload(context->current_rt, SRGB_BOTH); + } + else + { + surface_internal_preload(context->current_rt, SRGB_RGB); + } + + IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE); + + This->isInDraw = oldInDraw; } } - /* 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. - * Set the isInDraw to true to signal PreLoad that it has a context. Will be tricky - * when using offscreen rendering with multithreading - */ - This->isInDraw = TRUE; - - /* Do that before switching the context: - * Read the back buffer of the old drawable into the destination texture - */ - if(((IWineD3DSurfaceImpl *)This->lastActiveRenderTarget)->glDescription.srgbTextureName) { - surface_internal_preload(This->lastActiveRenderTarget, SRGB_BOTH); - } else { - surface_internal_preload(This->lastActiveRenderTarget, SRGB_RGB); - } - - /* Assume that the drawable will be modified by some other things now */ - IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, FALSE); - - This->isInDraw = oldInDraw; - } + context->draw_buffer_dirty = TRUE; + context->current_rt = target; return context; } -static void apply_draw_buffer(IWineD3DDeviceImpl *This, IWineD3DSurface *target, BOOL blit) +/* Context activation is done by the caller. */ +static void context_apply_draw_buffer(struct wined3d_context *context, BOOL blit) { + const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DSurface *rt = context->current_rt; IWineD3DSwapChain *swapchain; + IWineD3DDeviceImpl *device; - if (SUCCEEDED(IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain))) + device = ((IWineD3DSurfaceImpl *)rt)->resource.wineD3DDevice; + if (SUCCEEDED(IWineD3DSurface_GetContainer(rt, &IID_IWineD3DSwapChain, (void **)&swapchain))) { IWineD3DSwapChain_Release((IUnknown *)swapchain); ENTER_GL(); - glDrawBuffer(surface_get_gl_buffer(target, swapchain)); + glDrawBuffer(surface_get_gl_buffer(rt, swapchain)); checkGLcall("glDrawBuffers()"); LEAVE_GL(); } @@ -1473,12 +1949,12 @@ static void apply_draw_buffer(IWineD3DDeviceImpl *This, IWineD3DSurface *target, { if (GL_SUPPORT(ARB_DRAW_BUFFERS)) { - GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers)); + GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), device->draw_buffers)); checkGLcall("glDrawBuffers()"); } else { - glDrawBuffer(This->draw_buffers[0]); + glDrawBuffer(device->draw_buffers[0]); checkGLcall("glDrawBuffer()"); } } else { @@ -1488,7 +1964,7 @@ static void apply_draw_buffer(IWineD3DDeviceImpl *This, IWineD3DSurface *target, } else { - glDrawBuffer(This->offscreenBuffer); + glDrawBuffer(device->offscreenBuffer); checkGLcall("glDrawBuffer()"); } LEAVE_GL(); @@ -1508,89 +1984,75 @@ static void apply_draw_buffer(IWineD3DDeviceImpl *This, IWineD3DSurface *target, * usage: Prepares the context for blitting, drawing or other actions * *****************************************************************************/ -void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextUsage usage) { +struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage) +{ + struct wined3d_context *current_context = context_get_current(); DWORD tid = GetCurrentThreadId(); DWORD i, dirtyState, idx; BYTE shift; - WineD3DContext *context; const struct StateEntry *StateTable = This->StateTable; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; 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); - context->draw_buffer_dirty = TRUE; - This->lastActiveRenderTarget = target; - This->lastThread = tid; - } else { - /* Stick to the old context */ - context = This->activeContext; - } + + context = FindContext(This, target, tid); + + gl_info = context->gl_info; /* Activate the opengl context */ - if(last_device != This || context != This->activeContext) { - BOOL ret; + if (context != current_context) + { + if (!context_set_current(context)) ERR("Failed to activate the new context.\n"); + else This->frag_pipe->enable_extension((IWineD3DDevice *)This, !context->last_was_blit); - /* Prevent an unneeded context switch as those are expensive */ - if(context->glCtx && (context->glCtx == pwglGetCurrentContext())) { - TRACE("Already using gl context %p\n", context->glCtx); + if (context->vshader_const_dirty) + { + memset(context->vshader_const_dirty, 1, + sizeof(*context->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + This->highest_dirty_vs_const = GL_LIMITS(vshader_constantsF); } - else { - TRACE("Switching gl ctx to %p, hdc=%p ctx=%p\n", context, context->hdc, context->glCtx); - - 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); - } else { - This->frag_pipe->enable_extension((IWineD3DDevice *) This, FALSE); - } + if (context->pshader_const_dirty) + { + memset(context->pshader_const_dirty, 1, + sizeof(*context->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + This->highest_dirty_ps_const = GL_LIMITS(pshader_constantsF); } - 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; } switch (usage) { case CTXUSAGE_CLEAR: case CTXUSAGE_DRAWPRIM: if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - context_apply_fbo_state((IWineD3DDevice *)This); + ENTER_GL(); + context_apply_fbo_state(context); + LEAVE_GL(); } if (context->draw_buffer_dirty) { - apply_draw_buffer(This, target, FALSE); + context_apply_draw_buffer(context, FALSE); context->draw_buffer_dirty = FALSE; } break; case CTXUSAGE_BLIT: if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - if (This->render_offscreen) { + if (context->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); - ENTER_GL(); - GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); - checkGLcall("glFramebufferRenderbufferEXT"); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->dst_fbo); + context_attach_surface_fbo(context, GL_FRAMEBUFFER_EXT, 0, target); + context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, NULL, FALSE); LEAVE_GL(); } else { ENTER_GL(); - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - checkGLcall("glFramebufferRenderbufferEXT"); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); LEAVE_GL(); } context->draw_buffer_dirty = TRUE; } if (context->draw_buffer_dirty) { - apply_draw_buffer(This, target, TRUE); + context_apply_draw_buffer(context, TRUE); if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) { context->draw_buffer_dirty = FALSE; } @@ -1636,6 +2098,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU IWineD3DDeviceImpl_FindTexUnitMap(This); + ENTER_GL(); for(i=0; i < context->numDirtyEntries; i++) { dirtyState = context->dirtyArray[i]; idx = dirtyState >> 5; @@ -1643,6 +2106,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU context->isStateDirty[idx] &= ~(1 << shift); StateTable[dirtyState].apply(dirtyState, This->stateBlock, context); } + LEAVE_GL(); context->numDirtyEntries = 0; /* This makes the whole list clean */ context->last_was_blit = FALSE; break; @@ -1656,8 +2120,6 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU default: FIXME("Unexpected context usage requested\n"); } -} -WineD3DContext *getActiveContext(void) { - return last_device->activeContext; + return context; } diff --git a/reactos/dll/directx/wine/wined3d/cubetexture.c b/reactos/dll/directx/wine/wined3d/cubetexture.c index ce5f6b618bc..4b6900a87f8 100644 --- a/reactos/dll/directx/wine/wined3d/cubetexture.c +++ b/reactos/dll/directx/wine/wined3d/cubetexture.c @@ -25,11 +25,241 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); -#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + +#define GLINFO_LOCATION (*gl_info) + +static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) +{ + /* Override the IWineD3DResource Preload method. */ + IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + unsigned int i, j; + BOOL srgb_mode; + BOOL *dirty; + + switch (srgb) + { + case SRGB_RGB: + srgb_mode = FALSE; + break; + + case SRGB_BOTH: + cubetexture_internal_preload(iface, SRGB_RGB); + /* Fallthrough */ + + case SRGB_SRGB: + srgb_mode = TRUE; + break; + + default: + srgb_mode = This->baseTexture.is_srgb; + break; + } + dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; + + TRACE("(%p) : About to load texture: dirtified(%u).\n", This, *dirty); + + /* 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. */ + if (!device->isInDraw) + { + /* No danger of recursive calls, ActivateContext sets isInDraw to true + * when loading offscreen render targets into their texture. */ + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + } + + if (This->resource.format_desc->format == WINED3DFMT_P8 + || This->resource.format_desc->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 (*dirty) + { + for (i = 0; i < This->baseTexture.levels; ++i) + { + for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++j) + { + IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); + } + } + } + else + { + TRACE("(%p) Texture not dirty, nothing to do.\n" , iface); + } + + /* No longer dirty. */ + *dirty = FALSE; +} + +static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb) +{ + unsigned int i, j; + + TRACE("(%p) : Cleaning up.\n", This); + + for (i = 0; i < This->baseTexture.levels; ++i) + { + for (j = 0; j < 6; ++j) + { + IWineD3DSurface *surface = This->surfaces[j][i]; + + if (surface) + { + /* Clean out the texture name we gave to the surface so that the + * surface doesn't try and release it. */ + surface_set_texture_name(surface, 0, TRUE); + surface_set_texture_name(surface, 0, FALSE); + surface_set_texture_target(surface, 0); + IWineD3DSurface_SetContainer(surface, NULL); + surface_destroy_cb(surface); + } + } + } + basetexture_cleanup((IWineD3DBaseTexture *)This); +} + +HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) +{ + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + UINT pow2_edge_length; + unsigned int i, j; + UINT tmp_w; + HRESULT hr; + + /* 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", texture); + return WINED3DERR_INVALIDCALL; + } + + if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP) && pool != WINED3DPOOL_SCRATCH) + { + WARN("(%p) : Tried to create not supported cube texture.\n", texture); + return WINED3DERR_INVALIDCALL; + } + + /* Calculate levels for mip mapping */ + if (usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + levels = 1; + } + else if (!levels) + { + levels = wined3d_log2i(edge_length) + 1; + TRACE("Calculated levels = %u.\n", levels); + } + + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, + WINED3DRTYPE_CUBETEXTURE, device, 0, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize basetexture, returning %#x\n", hr); + return hr; + } + + /* Find the nearest pow2 match. */ + pow2_edge_length = 1; + while (pow2_edge_length < edge_length) pow2_edge_length <<= 1; + + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || (edge_length == pow2_edge_length)) + { + /* Precalculated scaling for 'faked' non power of two texture coords. */ + texture->baseTexture.pow2Matrix[0] = 1.0f; + texture->baseTexture.pow2Matrix[5] = 1.0f; + texture->baseTexture.pow2Matrix[10] = 1.0f; + texture->baseTexture.pow2Matrix[15] = 1.0f; + } + else + { + /* Precalculated scaling for 'faked' non power of two texture coords. */ + texture->baseTexture.pow2Matrix[0] = ((float)edge_length) / ((float)pow2_edge_length); + texture->baseTexture.pow2Matrix[5] = ((float)edge_length) / ((float)pow2_edge_length); + texture->baseTexture.pow2Matrix[10] = ((float)edge_length) / ((float)pow2_edge_length); + texture->baseTexture.pow2Matrix[15] = 1.0f; + texture->baseTexture.pow2Matrix_identity = FALSE; + } + + /* Generate all the surfaces. */ + tmp_w = edge_length; + for (i = 0; i < texture->baseTexture.levels; ++i) + { + /* Create the 6 faces. */ + for (j = 0; j < 6; ++j) + { + static const GLenum cube_targets[6] = + { + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, + }; + + hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_w, + format, usage, pool, i /* Level */, j, &texture->surfaces[j][i]); + if (FAILED(hr)) + { + FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr); + texture->surfaces[j][i] = NULL; + cubetexture_cleanup(texture, D3DCB_DefaultDestroySurface); + return hr; + } + + IWineD3DSurface_SetContainer(texture->surfaces[j][i], (IWineD3DBase *)texture); + TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[j][i]); + surface_set_texture_target(texture->surfaces[j][i], cube_targets[j]); + } + tmp_w = max(1, tmp_w >> 1); + } + texture->baseTexture.internal_preload = cubetexture_internal_preload; + + return WINED3D_OK; +} + +#undef GLINFO_LOCATION /* ******************************************* IWineD3DCubeTexture IUnknown parts follow ******************************************* */ + +#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + static HRESULT WINAPI IWineD3DCubeTextureImpl_QueryInterface(IWineD3DCubeTexture *iface, REFIID riid, LPVOID *ppobj) { IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; @@ -91,65 +321,6 @@ static DWORD WINAPI IWineD3DCubeTextureImpl_GetPriority(IWineD3DCubeTexture *ifa return resource_get_priority((IWineD3DResource *)iface); } -void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { - /* Override the IWineD3DResource Preload method */ - unsigned int i,j; - IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL srgb_mode; - BOOL *dirty; - - switch(srgb) { - case SRGB_RGB: srgb_mode = FALSE; break; - case SRGB_BOTH: cubetexture_internal_preload(iface, SRGB_RGB); - case SRGB_SRGB: srgb_mode = TRUE; break; - /* DONTKNOW, and shut up the compiler */ - default: srgb_mode = This->baseTexture.is_srgb; break; - } - dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; - - TRACE("(%p) : About to load texture: dirtified(%d)\n", This, *dirty); - - /* 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 - */ - if(!device->isInDraw) { - /* No danger of recursive calls, ActivateContext sets isInDraw to true when loading - * offscreen render targets into their texture - */ - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - - if (This->resource.format_desc->format == WINED3DFMT_P8 || This->resource.format_desc->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 (*dirty) { - for (i = 0; i < This->baseTexture.levels; i++) { - for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { - IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); - } - } - } else { - TRACE("(%p) Texture not dirty, nothing to do\n" , iface); - } - - /* No longer dirty */ - *dirty = FALSE; - return; -} - static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { cubetexture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); } @@ -219,6 +390,7 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_GetDirty(IWineD3DCubeTexture *iface) return basetexture_get_dirty((IWineD3DBaseTexture *)iface); } +/* Context activation is done by the caller. */ static HRESULT WINAPI IWineD3DCubeTextureImpl_BindTexture(IWineD3DCubeTexture *iface, BOOL srgb) { IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; BOOL set_gl_texture_desc; @@ -257,36 +429,13 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface) 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]) { - TRACE("(%p) : relay to BaseTexture\n", iface); - basetexture_apply_state_changes((IWineD3DBaseTexture *)iface, textureStates, samplerStates); -} - - /* ******************************************* IWineD3DCubeTexture IWineD3DCubeTexture parts follow ******************************************* */ static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) { IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - unsigned int i,j; - TRACE("(%p) : Cleaning up\n",This); - for (i = 0; i < This->baseTexture.levels; i++) { - for (j = 0; j < 6; j++) { - if (This->surfaces[j][i] != NULL) { - IWineD3DSurface *surface = This->surfaces[j][i]; - /* Clean out the texture name we gave to the surface so that the surface doesn't try and release it */ - surface_set_texture_name(surface, 0, TRUE); - surface_set_texture_name(surface, 0, FALSE); - surface_set_texture_target(surface, 0); - /* Cleanup the container */ - IWineD3DSurface_SetContainer(This->surfaces[j][i], 0); - D3DCB_DestroySurface(This->surfaces[j][i]); - } - } - } - basetexture_cleanup((IWineD3DBaseTexture *)iface); + + cubetexture_cleanup(This, D3DCB_DestroySurface); /* finally delete the object */ HeapFree(GetProcessHeap(), 0, This); } @@ -399,7 +548,6 @@ const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl = IWineD3DCubeTextureImpl_BindTexture, IWineD3DCubeTextureImpl_GetTextureDimensions, IWineD3DCubeTextureImpl_IsCondNP2, - IWineD3DCubeTextureImpl_ApplyStateChanges, /* IWineD3DCubeTexture */ IWineD3DCubeTextureImpl_Destroy, IWineD3DCubeTextureImpl_GetLevelDesc, diff --git a/reactos/dll/directx/wine/wined3d/device.c b/reactos/dll/directx/wine/wined3d/device.c index ec6d3f0422e..58e3b699d95 100644 --- a/reactos/dll/directx/wine/wined3d/device.c +++ b/reactos/dll/directx/wine/wined3d/device.c @@ -38,26 +38,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); /* Define the default light parameters as specified by MSDN */ const WINED3DLIGHT WINED3D_default_light = { - WINED3DLIGHT_DIRECTIONAL, /* Type */ - { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */ - { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */ - { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */ - { 0.0, 0.0, 0.0 }, /* Position x,y,z */ - { 0.0, 0.0, 1.0 }, /* Direction x,y,z */ - 0.0, /* Range */ - 0.0, /* Falloff */ - 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */ - 0.0, /* Theta */ - 0.0 /* Phi */ + WINED3DLIGHT_DIRECTIONAL, /* Type */ + { 1.0f, 1.0f, 1.0f, 0.0f }, /* Diffuse r,g,b,a */ + { 0.0f, 0.0f, 0.0f, 0.0f }, /* Specular r,g,b,a */ + { 0.0f, 0.0f, 0.0f, 0.0f }, /* Ambient r,g,b,a, */ + { 0.0f, 0.0f, 0.0f }, /* Position x,y,z */ + { 0.0f, 0.0f, 1.0f }, /* Direction x,y,z */ + 0.0f, /* Range */ + 0.0f, /* Falloff */ + 0.0f, 0.0f, 0.0f, /* Attenuation 0,1,2 */ + 0.0f, /* Theta */ + 0.0f /* Phi */ }; -/* static function declarations */ -static void IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource); - /********************************************************** * Global variable / Constants follow **********************************************************/ -const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */ +const float identity[] = +{ + 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, +}; /* When needed for comparisons */ /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these * actually have the same values in GL and D3D. */ @@ -169,6 +172,7 @@ static BOOL fixed_get_input(BYTE usage, BYTE usage_idx, unsigned int *regnum) return TRUE; } +/* Context activation is done by the caller. */ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, BOOL use_vshader, struct wined3d_stream_info *stream_info, BOOL *fixup) { @@ -178,7 +182,8 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, const DWORD *streams = declaration->streams; unsigned int i; - memset(stream_info, 0, sizeof(*stream_info)); + stream_info->use_map = 0; + stream_info->swizzle_map = 0; /* Check for transformed vertices, disable vertex shader if present. */ stream_info->position_transformed = declaration->position_transformed; @@ -440,6 +445,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice *iface, struct wined3d_buffer_desc *desc, const void *data, IUnknown *parent, IWineD3DBuffer **buffer) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(WINED3DFMT_UNKNOWN, &This->adapter->gl_info); struct wined3d_buffer *object; HRESULT hr; @@ -457,8 +463,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice *iface, FIXME("Ignoring access flags (pool)\n"); - hr = resource_init(&object->resource, WINED3DRTYPE_BUFFER, This, desc->byte_width, - desc->usage, WINED3DFMT_UNKNOWN, WINED3DPOOL_MANAGED, parent); + hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_BUFFER, This, desc->byte_width, + desc->usage, format_desc, WINED3DPOOL_MANAGED, parent); if (FAILED(hr)) { WARN("Failed to initialize resource, returning %#x\n", hr); @@ -469,8 +475,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice *iface, TRACE("Created resource %p\n", object); - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - TRACE("size %#x, usage=%#x, format %s, memory @ %p, iface @ %p\n", object->resource.size, object->resource.usage, debug_d3dformat(object->resource.format_desc->format), object->resource.allocatedMemory, object); @@ -535,7 +539,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac } object->vtbl = &wined3d_buffer_vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_BUFFER, This, Size, Usage, format_desc, Pool, parent); + hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_BUFFER, This, Size, Usage, format_desc, Pool, parent); if (FAILED(hr)) { WARN("Failed to initialize resource, returning %#x\n", hr); @@ -547,8 +551,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac TRACE("(%p) : Created resource %p\n", This, object); - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)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 = (IWineD3DBuffer *)object; @@ -602,7 +604,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface } object->vtbl = &wined3d_buffer_vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_BUFFER, This, Length, Usage, format_desc, Pool, parent); + hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_BUFFER, This, Length, Usage, format_desc, Pool, parent); if (FAILED(hr)) { WARN("Failed to initialize resource, returning %#x\n", hr); @@ -614,8 +616,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface TRACE("(%p) : Created resource %p\n", This, object); - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { object->flags |= WINED3D_BUFFER_CREATEBO; } @@ -897,171 +897,45 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, - UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, - IWineD3DSurface **ppSurface, WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, - WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, WINED3DSURFTYPE Impl, IUnknown *parent) +static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, + WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface, + DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, + WINED3DSURFTYPE Impl, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */ - unsigned int Size = 1; - const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(Format, &GLINFO_LOCATION); - UINT mul_4w, mul_4h; + IWineD3DSurfaceImpl *object; HRESULT hr; TRACE("(%p) Create surface\n",This); - if(MultisampleQuality > 0) { - FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality); - MultisampleQuality=0; + if (Impl == SURFACE_OPENGL && !This->adapter) + { + ERR("OpenGL surfaces are not available without OpenGL.\n"); + return WINED3DERR_NOTAVAILABLE; } - /** FIXME: Check that the format is supported - * by the device. - *******************************/ - - /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since - * 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 = (mul_4w * glDesc->byte_count * mul_4h) >> 1; - - } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 || - Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5 || - Format == WINED3DFMT_ATI2N) { - Size = (mul_4w * glDesc->byte_count * mul_4h); - } else { - /* The pitch is a multiple of 4 bytes */ - Size = ((Width * glDesc->byte_count) + This->surface_alignment - 1) & ~(This->surface_alignment - 1); - Size *= Height; - } - - if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale; - - /** Create and initialise the surface resource **/ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { - ERR("Out of memory\n"); + ERR("Failed to allocate surface memory.\n"); *ppSurface = NULL; return WINED3DERR_OUTOFVIDEOMEMORY; } - /* Look at the implementation and set the correct Vtable */ - switch(Impl) - { - case SURFACE_OPENGL: - /* Check if a 3D adapter is available when creating gl surfaces */ - if (!This->adapter) - { - ERR("OpenGL surfaces are not available without opengl\n"); - HeapFree(GetProcessHeap(), 0, object); - return WINED3DERR_NOTAVAILABLE; - } - object->lpVtbl = &IWineD3DSurface_Vtbl; - break; - - case SURFACE_GDI: - object->lpVtbl = &IWineGDISurface_Vtbl; - break; - - default: - /* To be sure to catch this */ - ERR("Unknown requested surface implementation %d!\n", Impl); - HeapFree(GetProcessHeap(), 0, object); - return WINED3DERR_INVALIDCALL; - } - - hr = resource_init(&object->resource, WINED3DRTYPE_SURFACE, This, Size, Usage, glDesc, Pool, parent); + hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable, + Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent); if (FAILED(hr)) { - WARN("Failed to initialize resource, returning %#x\n", hr); + WARN("Failed to initialize surface, returning %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); *ppSurface = NULL; return hr; } - TRACE("(%p) : Created resource %p\n", This, object); - - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + TRACE("(%p) : Created surface %p\n", This, object); *ppSurface = (IWineD3DSurface *)object; - /* "Standalone" surface */ - IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL); - - object->currentDesc.Width = Width; - object->currentDesc.Height = Height; - object->currentDesc.MultiSampleType = MultiSample; - object->currentDesc.MultiSampleQuality = MultisampleQuality; - object->glDescription.level = Level; - list_init(&object->overlays); - - /* Flags */ - 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; - - TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM); - - /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly - * this function is too deep to need to care about things like this. - * Levels need to be checked too, and possibly Type since they all affect what can be done. - * ****************************************/ - switch(Pool) { - case WINED3DPOOL_SCRATCH: - if(!Lockable) - FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE " - "which are mutually exclusive, setting lockable to TRUE\n"); - Lockable = TRUE; - break; - case WINED3DPOOL_SYSTEMMEM: - if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, " - "this is acceptable but unexpected (I can't know how the surface can be usable!)\n"); - case WINED3DPOOL_MANAGED: - if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a " - "Usage of DYNAMIC which are mutually exclusive, not doing " - "anything just telling you.\n"); - break; - case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */ - if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET) - && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable) - WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n"); - break; - default: - FIXME("(%p) Unknown pool %d\n", This, Pool); - break; - }; - - if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) { - FIXME("Trying to create a render target that isn't in the default pool\n"); - } - - /* mark the texture as dirty so that it gets loaded first time around*/ - surface_add_dirty_rect(*ppSurface, NULL); - TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", - This, Width, Height, Format, debug_d3dformat(Format), - (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size); - - list_init(&object->renderbuffers); - - /* Call the private setup routine */ - hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object); - if (FAILED(hr)) - { - ERR("Private setup failed, returning %#x\n", hr); - IWineD3DSurface_Release(*ppSurface); - *ppSurface = NULL; - return hr; - } - return hr; } @@ -1093,73 +967,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, WINED3DPOOL Pool, IWineD3DTexture **ppTexture, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info); IWineD3DTextureImpl *object; - unsigned int i; - UINT tmpW; - UINT tmpH; HRESULT hr; - unsigned int pow2Width; - unsigned int pow2Height; TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage); TRACE("Format %#x (%s), Pool %#x, ppTexture %p, parent %p\n", Format, debug_d3dformat(Format), Pool, ppTexture, parent); - /* 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); - return WINED3DERR_INVALIDCALL; - } - - /* Non-power2 support */ - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) - { - pow2Width = Width; - pow2Height = Height; - } - else - { - /* Find the nearest pow2 match */ - 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"); - return WINED3DERR_INVALIDCALL; - } - Levels = 1; - } - } - - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) - { - if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) - { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - if (Levels > 1) - { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - Levels = 1; - } - else if (!Levels) - { - Levels = wined3d_log2i(max(Width, Height)) + 1; - TRACE("Calculated levels = %d\n", Levels); - } - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { @@ -1169,106 +983,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, } object->lpVtbl = &IWineD3DTexture_Vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_TEXTURE, This, 0, Usage, format_desc, Pool, parent); + + hr = texture_init(object, Width, Height, Levels, This, Usage, Format, Pool, parent); if (FAILED(hr)) { - WARN("Failed to initialize resource, returning %#x\n", hr); + WARN("Failed to initialize texture, returning %#x\n", hr); HeapFree(GetProcessHeap(), 0, object); *ppTexture = NULL; return hr; } - TRACE("(%p) : Created resource %p\n", This, object); - - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - *ppTexture = (IWineD3DTexture *)object; - basetexture_init(&object->baseTexture, Levels, Usage); + TRACE("(%p) : Created texture %p\n", This, object); - if (object->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) - { - object->baseTexture.minMipLookup = minMipLookup; - object->baseTexture.magLookup = magLookup; - } else { - object->baseTexture.minMipLookup = minMipLookup_noFilter; - object->baseTexture.magLookup = magLookup_noFilter; - } - - /** 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. - 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; - 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))) - { - if ((Width != 1) || (Height != 1)) { - object->baseTexture.pow2Matrix_identity = FALSE; - } - - 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 { - if ((Width != pow2Width) || (Height != pow2Height)) { - object->baseTexture.pow2Matrix_identity = FALSE; - object->baseTexture.pow2Matrix[0] = (((float)Width) / ((float)pow2Width)); - object->baseTexture.pow2Matrix[5] = (((float)Height) / ((float)pow2Height)); - } else { - 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 = FALSE; - } - TRACE(" xf(%f) yf(%f)\n", object->baseTexture.pow2Matrix[0], object->baseTexture.pow2Matrix[5]); - - /* Generate all the surfaces */ - tmpW = Width; - tmpH = Height; - for (i = 0; i < object->baseTexture.levels; i++) - { - /* use the callback to create the texture surface */ - hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpH, Format, - Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i]); - if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) { - FIXME("Failed to create surface %p\n", object); - /* clean up */ - object->surfaces[i] = NULL; - IWineD3DTexture_Release((IWineD3DTexture *)object); - - *ppTexture = NULL; - return hr; - } - - IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object); - TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]); - surface_set_texture_target(object->surfaces[i], object->target); - /* calculate the next mipmap level */ - tmpW = max(1, tmpW >> 1); - tmpH = max(1, tmpH >> 1); - } - object->baseTexture.internal_preload = texture_internal_preload; - - TRACE("(%p) : Created texture %p\n", This, object); return WINED3D_OK; } @@ -1277,47 +1005,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa WINED3DPOOL Pool, IWineD3DVolumeTexture **ppVolumeTexture, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info); IWineD3DVolumeTextureImpl *object; - unsigned int i; - UINT tmpW; - UINT tmpH; - UINT tmpD; HRESULT hr; - /* 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); - return WINED3DERR_INVALIDCALL; - } - if(!GL_SUPPORT(EXT_TEXTURE3D)) { - WARN("(%p) : Texture cannot be created - no volume texture support\n", This); - return WINED3DERR_INVALIDCALL; - } - - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) - { - if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) - { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - if (Levels > 1) - { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - Levels = 1; - } - else if (!Levels) - { - Levels = wined3d_log2i(max(max(Width, Height), Depth)) + 1; - TRACE("Calculated levels = %d\n", Levels); - } + TRACE("(%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, + Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool)); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) @@ -1328,69 +1020,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa } object->lpVtbl = &IWineD3DVolumeTexture_Vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_VOLUMETEXTURE, This, 0, Usage, format_desc, Pool, parent); + hr = volumetexture_init(object, Width, Height, Depth, Levels, This, Usage, Format, Pool, parent); if (FAILED(hr)) { - WARN("Failed to initialize resource, returning %#x\n", hr); + WARN("Failed to initialize volumetexture, returning %#x\n", hr); HeapFree(GetProcessHeap(), 0, object); *ppVolumeTexture = NULL; return hr; } - TRACE("(%p) : Created resource %p\n", This, object); + TRACE("(%p) : Created volume texture %p.\n", This, object); + *ppVolumeTexture = (IWineD3DVolumeTexture *)object; - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - - basetexture_init(&object->baseTexture, Levels, Usage); - - TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, - Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool)); - - /* Is NP2 support for volumes needed? */ - object->baseTexture.pow2Matrix[ 0] = 1.0; - object->baseTexture.pow2Matrix[ 5] = 1.0; - object->baseTexture.pow2Matrix[10] = 1.0; - object->baseTexture.pow2Matrix[15] = 1.0; - - if (object->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) - { - object->baseTexture.minMipLookup = minMipLookup; - object->baseTexture.magLookup = magLookup; - } else { - object->baseTexture.minMipLookup = minMipLookup_noFilter; - object->baseTexture.magLookup = magLookup_noFilter; - } - - /* Generate all the surfaces */ - tmpW = Width; - tmpH = Height; - tmpD = Depth; - - for (i = 0; i < object->baseTexture.levels; i++) - { - HRESULT hr; - /* Create the volume */ - hr = IWineD3DDeviceParent_CreateVolume(This->device_parent, parent, - tmpW, tmpH, tmpD, Format, Pool, Usage, &object->volumes[i]); - if(FAILED(hr)) { - ERR("Creating a volume for the volume texture failed(%08x)\n", hr); - IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object); - *ppVolumeTexture = NULL; - return hr; - } - - /* Set its container to this object */ - IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object); - - /* calculate the next mipmap level */ - tmpW = max(1, tmpW >> 1); - tmpH = max(1, tmpH >> 1); - tmpD = max(1, tmpD >> 1); - } - object->baseTexture.internal_preload = volumetexture_internal_preload; - - *ppVolumeTexture = (IWineD3DVolumeTexture *) object; - TRACE("(%p) : Created volume texture %p\n", This, object); return WINED3D_OK; } @@ -1417,7 +1058,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, } object->lpVtbl = &IWineD3DVolume_Vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_VOLUME, This, + hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_VOLUME, This, Width * Height * Depth * format_desc->byte_count, Usage, format_desc, Pool, parent); if (FAILED(hr)) { @@ -1429,8 +1070,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, TRACE("(%p) : Created resource %p\n", This, object); - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - *ppVolume = (IWineD3DVolume *)object; TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, @@ -1456,47 +1095,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface WINED3DPOOL Pool, IWineD3DCubeTexture **ppCubeTexture, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info); IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/ - unsigned int i, j; - UINT tmpW; HRESULT hr; - unsigned int pow2EdgeLength; - - /* 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); - return WINED3DERR_INVALIDCALL; - } - - if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP) && Pool != WINED3DPOOL_SCRATCH) { - WARN("(%p) : Tried to create not supported cube texture\n", This); - return WINED3DERR_INVALIDCALL; - } - - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) - { - if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) - { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - if (Levels > 1) - { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - - Levels = 1; - } - else if (!Levels) - { - Levels = wined3d_log2i(EdgeLength) + 1; - TRACE("Calculated levels = %d\n", Levels); - } object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) @@ -1507,85 +1107,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface } object->lpVtbl = &IWineD3DCubeTexture_Vtbl; - hr = resource_init(&object->resource, WINED3DRTYPE_CUBETEXTURE, This, 0, Usage, format_desc, Pool, parent); + hr = cubetexture_init(object, EdgeLength, Levels, This, Usage, Format, Pool, parent); if (FAILED(hr)) { - WARN("Failed to initialize resource, returning %#x\n", hr); + WARN("Failed to initialize cubetexture, returning %#x\n", hr); HeapFree(GetProcessHeap(), 0, object); *ppCubeTexture = NULL; return hr; } - TRACE("(%p) : Created resource %p\n", This, object); - - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); - - basetexture_init(&object->baseTexture, Levels, Usage); - - TRACE("(%p) Create Cube Texture\n", This); - - /* Find the nearest pow2 match */ - pow2EdgeLength = 1; - while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1; - - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || (EdgeLength == pow2EdgeLength)) { - /* Precalculated scaling for 'faked' non power of two texture coords */ - object->baseTexture.pow2Matrix[ 0] = 1.0; - object->baseTexture.pow2Matrix[ 5] = 1.0; - object->baseTexture.pow2Matrix[10] = 1.0; - object->baseTexture.pow2Matrix[15] = 1.0; - } else { - /* Precalculated scaling for 'faked' non power of two texture coords */ - object->baseTexture.pow2Matrix[ 0] = ((float)EdgeLength) / ((float)pow2EdgeLength); - object->baseTexture.pow2Matrix[ 5] = ((float)EdgeLength) / ((float)pow2EdgeLength); - object->baseTexture.pow2Matrix[10] = ((float)EdgeLength) / ((float)pow2EdgeLength); - object->baseTexture.pow2Matrix[15] = 1.0; - object->baseTexture.pow2Matrix_identity = FALSE; - } - - if (object->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) - { - object->baseTexture.minMipLookup = minMipLookup; - object->baseTexture.magLookup = magLookup; - } else { - object->baseTexture.minMipLookup = minMipLookup_noFilter; - object->baseTexture.magLookup = magLookup_noFilter; - } - - /* Generate all the surfaces */ - tmpW = EdgeLength; - for (i = 0; i < object->baseTexture.levels; i++) { - - /* Create the 6 faces */ - for (j = 0; j < 6; j++) { - static const GLenum cube_targets[6] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB - }; - - hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpW, - Format, Usage, Pool, i /* Level */, j, &object->surfaces[j][i]); - if (FAILED(hr)) - { - FIXME("(%p) Failed to create surface\n",object); - IWineD3DCubeTexture_Release((IWineD3DCubeTexture *)object); - *ppCubeTexture = NULL; - return hr; - } - IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object); - TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]); - surface_set_texture_target(object->surfaces[j][i], cube_targets[j]); - } - tmpW = max(1, tmpW >> 1); - } - object->baseTexture.internal_preload = cubetexture_internal_preload; - TRACE("(%p) : Created Cube Texture %p\n", This, object); - *ppCubeTexture = (IWineD3DCubeTexture *) object; + *ppCubeTexture = (IWineD3DCubeTexture *)object; + return WINED3D_OK; } @@ -1659,32 +1192,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE /* allocated the 'extended' data based on the type of query requested */ switch(Type){ case WINED3DQUERYTYPE_OCCLUSION: - object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData)); - ((WineQueryOcclusionData *)(object->extendedData))->ctx = This->activeContext; + object->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query)); + ((struct wined3d_occlusion_query *)object->extendedData)->context = NULL; + break; - if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) { - TRACE("(%p) Allocating data for an occlusion query\n", This); - - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId)); - LEAVE_GL(); - break; - } case WINED3DQUERYTYPE_EVENT: - object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData)); - ((WineQueryEventData *)(object->extendedData))->ctx = This->activeContext; - - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - if(GL_SUPPORT(APPLE_FENCE)) { - GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData *)(object->extendedData))->fenceId)); - checkGLcall("glGenFencesAPPLE"); - } else if(GL_SUPPORT(NV_FENCE)) { - GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData *)(object->extendedData))->fenceId)); - checkGLcall("glGenFencesNV"); - } - LEAVE_GL(); + object->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_event_query)); + ((struct wined3d_event_query *)object->extendedData)->context = NULL; break; case WINED3DQUERYTYPE_VCACHE: @@ -2327,7 +1841,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3D return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) { +static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, + const DWORD *pFunction, const struct wined3d_shader_signature *output_signature, + IWineD3DVertexShader **ppVertexShader, IUnknown *parent) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */ HRESULT hr = WINED3D_OK; @@ -2350,11 +1867,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac TRACE("(%p) : Created vertex shader %p\n", This, *ppVertexShader); - if (vertex_declaration) { - IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration); - } - - hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction, NULL); + hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction, output_signature); if (FAILED(hr)) { WARN("(%p) : Failed to set function, returning %#x\n", iface, hr); @@ -2468,9 +1981,8 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi bm.bmHeight = 32; } - hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5, - TRUE, FALSE, 0, &This->logo_surface, WINED3DRTYPE_SURFACE, 0, - WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL, NULL); + hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5, TRUE, + FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL, NULL); if(FAILED(hr)) { ERR("Wine logo requested, but failed to create surface\n"); goto out; @@ -2500,6 +2012,7 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi return; } +/* Context activation is done by the caller. */ static void create_dummy_textures(IWineD3DDeviceImpl *This) { unsigned int i; /* Under DirectX you can have texture stage operations even if no texture is @@ -2601,12 +2114,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, This->texUnitMap[state] = state; This->rev_tex_unit_map[state] = state; } else { - This->texUnitMap[state] = -1; - This->rev_tex_unit_map[state] = -1; + This->texUnitMap[state] = WINED3D_UNMAPPED_STAGE; + This->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE; } } - /* Setup the implicit swapchain */ + /* Setup the implicit swapchain. This also initializes a context. */ TRACE("Creating implicit swapchain\n"); hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); @@ -2627,16 +2140,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, if(swapchain->backBuffer && swapchain->backBuffer[0]) { TRACE("Setting rendertarget to %p\n", swapchain->backBuffer); This->render_targets[0] = swapchain->backBuffer[0]; - This->lastActiveRenderTarget = swapchain->backBuffer[0]; } else { TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer); This->render_targets[0] = swapchain->frontBuffer; - This->lastActiveRenderTarget = swapchain->frontBuffer; } IWineD3DSurface_AddRef(This->render_targets[0]); - This->activeContext = swapchain->context[0]; - This->lastThread = GetCurrentThreadId(); /* Depth Stencil support */ This->stencilBufferTarget = This->auto_depth_stencil_buffer; @@ -2682,7 +2191,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, case ORM_BACKBUFFER: { - if(This->activeContext->aux_buffers > 0) { + if (context_get_current()->aux_buffers > 0) + { TRACE("Using auxilliary buffer for offscreen rendering\n"); This->offscreenBuffer = GL_AUX0; } else { @@ -2698,7 +2208,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, /* Clear the screen */ IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0, - 0x00, 1.0, 0); + 0x00, 1.0f, 0); This->d3d_initialized = TRUE; @@ -2787,7 +2297,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D /* 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); + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); if(This->logo_surface) IWineD3DSurface_Release(This->logo_surface); @@ -2834,11 +2344,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D * private data, it might contain opengl pointers */ if(This->depth_blt_texture) { + ENTER_GL(); glDeleteTextures(1, &This->depth_blt_texture); + LEAVE_GL(); This->depth_blt_texture = 0; } if (This->depth_blt_rb) { + ENTER_GL(); GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb)); + LEAVE_GL(); This->depth_blt_rb = 0; This->depth_blt_rb_w = 0; This->depth_blt_rb_h = 0; @@ -3269,7 +2783,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed * most wanted */ - if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) { + if (pLight->Attenuation0 < 0.0f || pLight->Attenuation1 < 0.0f || pLight->Attenuation2 < 0.0f) + { WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n"); return WINED3DERR_INVALIDCALL; } @@ -3331,7 +2846,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I object->lightPosn[0] = -pLight->Direction.x; object->lightPosn[1] = -pLight->Direction.y; object->lightPosn[2] = -pLight->Direction.z; - object->lightPosn[3] = 0.0; + object->lightPosn[3] = 0.0f; object->exponent = 0.0f; object->cutoff = 180.0f; break; @@ -3341,13 +2856,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I object->lightPosn[0] = pLight->Position.x; object->lightPosn[1] = pLight->Position.y; object->lightPosn[2] = pLight->Position.z; - object->lightPosn[3] = 1.0; + object->lightPosn[3] = 1.0f; /* Direction */ object->lightDirn[0] = pLight->Direction.x; object->lightDirn[1] = pLight->Direction.y; object->lightDirn[2] = pLight->Direction.z; - object->lightDirn[3] = 1.0; + object->lightDirn[3] = 1.0f; /* * opengl-ish and d3d-ish spot lights use too different models for the @@ -3362,14 +2877,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I * will always be 1.0 for both of them, and we don't have to care for the * rest of the rather complex calculation */ - object->exponent = 0; + object->exponent = 0.0f; } else { rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff); - if (rho < 0.0001) rho = 0.0001f; - object->exponent = -0.3/log(cos(rho/2)); + if (rho < 0.0001f) rho = 0.0001f; + object->exponent = -0.3f/logf(cosf(rho/2)); } - if (object->exponent > 128.0) { - object->exponent = 128.0; + if (object->exponent > 128.0f) + { + object->exponent = 128.0f; } object->cutoff = pLight->Phi*90/M_PI; @@ -3420,9 +2936,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D struct list *e; TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable); - /* Tests show true = 128...not clear why */ - Enable = Enable? 128: 0; - LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) { lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry); if(lightInfo->OriginalIndex == Index) break; @@ -4123,18 +3636,21 @@ static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) } } -static void device_map_stage(IWineD3DDeviceImpl *This, int stage, int unit) { - int i = This->rev_tex_unit_map[unit]; - int j = This->texUnitMap[stage]; +static void device_map_stage(IWineD3DDeviceImpl *This, DWORD stage, DWORD unit) +{ + DWORD i = This->rev_tex_unit_map[unit]; + DWORD j = This->texUnitMap[stage]; This->texUnitMap[stage] = unit; - if (i != -1 && i != stage) { - This->texUnitMap[i] = -1; + if (i != WINED3D_UNMAPPED_STAGE && i != stage) + { + This->texUnitMap[i] = WINED3D_UNMAPPED_STAGE; } This->rev_tex_unit_map[unit] = stage; - if (j != -1 && j != unit) { - This->rev_tex_unit_map[j] = -1; + if (j != WINED3D_UNMAPPED_STAGE && j != unit) + { + This->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE; } } @@ -4228,14 +3744,12 @@ static void device_map_psamplers(IWineD3DDeviceImpl *This) { } static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshader_sampler_tokens, - const DWORD *vshader_sampler_tokens, int unit) + const DWORD *vshader_sampler_tokens, DWORD unit) { - int current_mapping = This->rev_tex_unit_map[unit]; + DWORD current_mapping = This->rev_tex_unit_map[unit]; - if (current_mapping == -1) { - /* Not currently used */ - return TRUE; - } + /* Not currently used */ + if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE; if (current_mapping < MAX_FRAGMENT_SAMPLERS) { /* Used by a fragment sampler */ @@ -4250,14 +3764,14 @@ static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshad } /* Used by a vertex sampler */ - return !vshader_sampler_tokens[current_mapping]; + return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS]; } static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type; const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL; - int start = GL_LIMITS(combined_samplers) - 1; + int start = min(MAX_COMBINED_SAMPLERS, GL_LIMITS(combined_samplers)) - 1; int i; if (ps) { @@ -4269,7 +3783,7 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { } for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { - int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS; + DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS; if (vshader_sampler_type[i]) { if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE) @@ -4510,6 +4024,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF( return WINED3D_OK; } +/* Context activation is done by the caller. */ #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags, @@ -4522,12 +4037,12 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn BOOL doClip; DWORD numTextures; - if (stream_info->elements[WINED3D_FFP_NORMAL].data) + if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL)) { WARN(" lighting state not saved yet... Some strange stuff may happen !\n"); } - if (!stream_info->elements[WINED3D_FFP_POSITION].data) + if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION))) { ERR("Source has no position mask\n"); return WINED3DERR_INVALIDCALL; @@ -4637,10 +4152,10 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]); /* Multiplication with world, view and projection matrix */ - x = (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41); - y = (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42); - z = (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43); - rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44); + x = (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0f * mat.u.s._41); + y = (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0f * mat.u.s._42); + z = (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0f * mat.u.s._43); + rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0f * mat.u.s._44); TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw); @@ -4663,7 +4178,7 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn if( !doClip || ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) && - (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && + (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && ( rhw > eps ) ) ) { /* "Normal" viewport transformation (not clipped) @@ -4760,7 +4275,8 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn if (DestFVF & WINED3DFVF_DIFFUSE) { const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE]; const DWORD *color_d = (const DWORD *)(element->data + i * element->stride); - if(!color_d) { + if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE))) + { static BOOL warned = FALSE; if(!warned) { @@ -4787,11 +4303,13 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn } } - if (DestFVF & WINED3DFVF_SPECULAR) { + if (DestFVF & WINED3DFVF_SPECULAR) + { /* What's the color value in the feedback buffer? */ const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR]; const DWORD *color_s = (const DWORD *)(element->data + i * element->stride); - if(!color_s) { + if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR))) + { static BOOL warned = FALSE; if(!warned) { @@ -4821,7 +4339,8 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn for (tex_index = 0; tex_index < numTextures; tex_index++) { const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index]; const float *tex_coord = (const float *)(element->data + i * element->stride); - if(!tex_coord) { + if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index)))) + { ERR("No source texture, but destination requests one\n"); dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float); if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float); @@ -4865,7 +4384,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, } /* Need any context to write to the vbo. */ - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP * control the streamIsUP flag, thus restore it afterwards. @@ -4883,7 +4402,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, */ for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i) { - struct wined3d_stream_info_element *e = &stream_info.elements[i]; + struct wined3d_stream_info_element *e; + + if (!(stream_info.use_map & (1 << i))) continue; + + e = &stream_info.elements[i]; if (e->buffer_object) { struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; @@ -5331,9 +4854,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { return WINED3DERR_INVALIDCALL; } - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ - glFlush(); + wglFlush(); /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever * fails */ @@ -5375,6 +4898,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa UINT drawable_width, drawable_height; IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget; IWineD3DSwapChainImpl *swapchain = NULL; + struct wined3d_context *context; /* 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 @@ -5410,9 +4934,10 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa } } - target->get_drawable_size(target, &drawable_width, &drawable_height); + context = ActivateContext(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR); + + target->get_drawable_size(context, &drawable_width, &drawable_height); - ActivateContext(This, (IWineD3DSurface *) target, CTXUSAGE_CLEAR); ENTER_GL(); /* Only set the values up once, as they are not changing */ @@ -5424,7 +4949,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa } if (Flags & WINED3DCLEAR_ZBUFFER) { - DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; glDepthMask(GL_TRUE); glClearDepth(Z); checkGLcall("glClearDepth"); @@ -5433,19 +4958,19 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa 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); + surface_load_ds_location(This->stencilBufferTarget, context, location); } else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && ( This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 || This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width || This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) { - surface_load_ds_location(This->stencilBufferTarget, location); + surface_load_ds_location(This->stencilBufferTarget, context, location); } else if (Count > 0 && pRects && ( pRects[0].x1 > 0 || pRects[0].y1 > 0 || pRects[0].x2 < depth_stencil->currentDesc.Width || pRects[0].y2 < depth_stencil->currentDesc.Height)) { - surface_load_ds_location(This->stencilBufferTarget, location); + surface_load_ds_location(This->stencilBufferTarget, context, location); } } @@ -5470,7 +4995,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) { IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect); } - if(This->render_offscreen) { + if (context->render_offscreen) + { glScissor(vp_rect.left, vp_rect.top, vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top); } else { @@ -5502,7 +5028,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa continue; } - if(This->render_offscreen) { + if (context->render_offscreen) + { glScissor(curRect.x1, curRect.y1, curRect.x2 - curRect.x1, curRect.y2 - curRect.y1); } else { @@ -5530,11 +5057,11 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa /* 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); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); } if (Flags & WINED3DCLEAR_ZBUFFER) { /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */ - DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; surface_modify_ds_location(This->stencilBufferTarget, location); } @@ -5542,7 +5069,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)target, &IID_IWineD3DSwapChain, (void **)&swapchain))) { if (target == (IWineD3DSurfaceImpl*) swapchain->frontBuffer) { - glFlush(); + wglFlush(); } IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } @@ -6203,6 +5730,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, * NOTE: move code to surface to accomplish this ****************************************/ IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface; + IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)pDestinationSurface; int srcWidth, srcHeight; unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight; WINED3DFORMAT destFormat, srcFormat; @@ -6211,31 +5739,28 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, WINED3DPOOL srcPool, destPool; int offset = 0; int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */ - glDescriptor *glDescription = NULL; const struct GlPixelFormatDesc *src_format_desc, *dst_format_desc; GLenum dummy; - int sampler; + DWORD sampler; int bpp; CONVERT_TYPES convert = NO_CONVERSION; WINED3DSURFACE_DESC winedesc; TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); - memset(&winedesc, 0, sizeof(winedesc)); - winedesc.Width = &srcSurfaceWidth; - winedesc.Height = &srcSurfaceHeight; - winedesc.Pool = &srcPool; - winedesc.Format = &srcFormat; IWineD3DSurface_GetDesc(pSourceSurface, &winedesc); - - winedesc.Width = &destSurfaceWidth; - winedesc.Height = &destSurfaceHeight; - winedesc.Pool = &destPool; - winedesc.Format = &destFormat; - winedesc.Size = &destSize; + srcSurfaceWidth = winedesc.width; + srcSurfaceHeight = winedesc.height; + srcPool = winedesc.pool; + srcFormat = winedesc.format; IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); + destSurfaceWidth = winedesc.width; + destSurfaceHeight = winedesc.height; + destPool = winedesc.pool; + destFormat = winedesc.format; + destSize = winedesc.size; if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){ WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface); @@ -6246,8 +5771,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, * destination's sysmem copy. If surface conversion is needed, use BltFast instead to * copy in sysmem and use regular surface loading. */ - d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE, TRUE, - &dummy, &dummy, &dummy, &convert, &bpp, FALSE); + d3dfmt_get_conv(dst_impl, FALSE, TRUE, &dummy, &dummy, &dummy, &convert, &bpp, FALSE); if(convert != NO_CONVERSION) { return IWineD3DSurface_BltFast(pDestinationSurface, pDestPoint ? pDestPoint->x : 0, @@ -6263,7 +5787,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); } - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); @@ -6274,10 +5798,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, surface_internal_preload(pDestinationSurface, SRGB_RGB); IWineD3DSurface_BindTexture(pDestinationSurface, FALSE); - IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription); - src_format_desc = ((IWineD3DSurfaceImpl *)pSrcSurface)->resource.format_desc; - dst_format_desc = ((IWineD3DSurfaceImpl *)pDestinationSurface)->resource.format_desc; + dst_format_desc = dst_impl->resource.format_desc; /* this needs to be done in lines if the sourceRect != the sourceWidth */ srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth; @@ -6300,7 +5822,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, offset += pSourceRect->top * srcSurfaceWidth * src_format_desc->byte_count; } TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n", - This, glDescription->level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat, + This, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, IWineD3DSurface_GetData(pSourceSurface), offset); /* Sanity check */ @@ -6322,7 +5844,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, for (j = destTop; j < (srcHeight + destTop); ++j) { - glTexSubImage2D(glDescription->target, glDescription->level, destLeft, j, + glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, j, srcWidth, 1, dst_format_desc->glFormat, dst_format_desc->glType,data); data += rowoffset; } @@ -6330,28 +5852,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, } else { /* Full width, so just write out the whole texture */ const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset; - if (WINED3DFMT_DXT1 == destFormat || - WINED3DFMT_DXT2 == destFormat || - WINED3DFMT_DXT3 == destFormat || - WINED3DFMT_DXT4 == destFormat || - WINED3DFMT_DXT5 == destFormat) { - if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { - if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) { - /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */ - FIXME("Updating part of a compressed texture is not supported at the moment\n"); - } if (destFormat != srcFormat) { - FIXME("Updating mixed format compressed texture is not curretly support\n"); - } else { - GL_EXTCALL(glCompressedTexImage2DARB(glDescription->target, glDescription->level, - dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data)); - } - } else { - FIXME("Attempting to update a DXT compressed texture without hardware support\n"); + if (dst_format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) + { + /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */ + FIXME("Updating part of a compressed texture is not supported.\n"); } - - - } else { - glTexSubImage2D(glDescription->target, glDescription->level, destLeft, destTop, + if (destFormat != srcFormat) + { + FIXME("Updating mixed format compressed textures is not supported.\n"); + } + else + { + GL_EXTCALL(glCompressedTexImage2DARB(dst_impl->texture_target, dst_impl->texture_level, + dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data)); + } + } + else + { + glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, data); } } @@ -6361,7 +5881,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE); sampler = This->rev_tex_unit_map[0]; - if (sampler != -1) { + if (sampler != WINED3D_UNMAPPED_STAGE) + { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler)); } @@ -6503,6 +6024,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, const WINED3DRECT *rect, const float color[4]) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct wined3d_context *context; IWineD3DSwapChain *swapchain; swapchain = get_swapchain(surface); @@ -6511,21 +6033,20 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, TRACE("Surface %p is onscreen\n", surface); - ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD); + context = ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD); ENTER_GL(); - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); buffer = surface_get_gl_buffer(surface, swapchain); glDrawBuffer(buffer); checkGLcall("glDrawBuffer()"); } else { TRACE("Surface %p is offscreen\n", surface); - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + context = ActivateContext(This, NULL, 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"); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->dst_fbo); + context_attach_surface_fbo(context, GL_FRAMEBUFFER_EXT, 0, surface); + context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, NULL, FALSE); } if (rect) { @@ -6553,13 +6074,6 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, glClear(GL_COLOR_BUFFER_BIT); checkGLcall("glClear"); - 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()"); - } - if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) { glDrawBuffer(GL_BACK); @@ -6697,7 +6211,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD BltFx.dwSize = sizeof(BltFx); BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format_desc->format); return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL, - WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE); + WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); } } @@ -6735,16 +6249,16 @@ static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *ifac WARN("Converting to WINED3DCOLOR, this might give incorrect results\n"); - c = ((DWORD)(color[2] * 255.0)); - c |= ((DWORD)(color[1] * 255.0)) << 8; - c |= ((DWORD)(color[0] * 255.0)) << 16; - c |= ((DWORD)(color[3] * 255.0)) << 24; + c = ((DWORD)(color[2] * 255.0f)); + c |= ((DWORD)(color[1] * 255.0f)) << 8; + c |= ((DWORD)(color[0] * 255.0f)) << 16; + c |= ((DWORD)(color[3] * 255.0f)) << 24; /* Just forward this to the DirectDraw blitting engine */ memset(&BltFx, 0, sizeof(BltFx)); BltFx.dwSize = sizeof(BltFx); BltFx.u5.dwFillColor = argb_to_fmt(c, ((IWineD3DSurfaceImpl *)surface)->resource.format_desc->format); - hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE); + hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT); if (FAILED(hr)) { ERR("Blt failed, hr %#x\n", hr); @@ -6829,6 +6343,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa /* What to do about the context here in the case of multithreading? Not sure. * This function is called by IDirect3D7::CreateDevice so in theory its initialization code */ + WARN("No active context?\n"); + ENTER_GL(); if(!Swapchain->backBuffer[0]) { /* GL was told to draw to the front buffer at creation, @@ -6887,6 +6403,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */ IWineD3DSwapChain *src_swapchain, *dst_swapchain; + struct wined3d_context *context; GLenum gl_filter; POINT offset = {0, 0}; @@ -6910,11 +6427,16 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED /* Attach src surface to src fbo */ src_swapchain = get_swapchain(src_surface); + dst_swapchain = get_swapchain(dst_surface); + + if (src_swapchain) context = ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD); + else if (dst_swapchain) context = ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD); + else context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + if (src_swapchain) { 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); @@ -6934,28 +6456,25 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED } ENTER_GL(); - GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0)); + context_bind_fbo(context, GL_READ_FRAMEBUFFER_EXT, NULL); glReadBuffer(buffer); checkGLcall("glReadBuffer()"); } else { TRACE("Source surface %p is offscreen\n", src_surface); ENTER_GL(); - context_bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->activeContext->src_fbo); - context_attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface); + context_bind_fbo(context, GL_READ_FRAMEBUFFER_EXT, &context->src_fbo); + context_attach_surface_fbo(context, 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"); + context_attach_depth_stencil_fbo(context, GL_READ_FRAMEBUFFER_EXT, NULL, FALSE); } LEAVE_GL(); /* Attach dst surface to dst fbo */ - dst_swapchain = get_swapchain(dst_surface); if (dst_swapchain) { 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); @@ -6976,24 +6495,18 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED } ENTER_GL(); - GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)); + context_bind_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, NULL); glDrawBuffer(buffer); checkGLcall("glDrawBuffer()"); } else { TRACE("Destination surface %p is offscreen\n", dst_surface); - /* No src or dst swapchain? Make sure some context is active(multithreading) */ - if(!src_swapchain) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - ENTER_GL(); - context_bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo); - context_attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface); + context_bind_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, &context->dst_fbo); + context_attach_surface_fbo(context, 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"); + context_attach_depth_stencil_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, NULL, FALSE); } glDisable(GL_SCISSOR_TEST); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); @@ -7010,13 +6523,6 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED 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()"); - } - /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */ if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) { @@ -7070,10 +6576,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, viewport.MaxZ = 1.0f; viewport.MinZ = 0.0f; IWineD3DDeviceImpl_SetViewport(iface, &viewport); - /* Make sure the viewport state is dirty, because the render_offscreen thing affects it. - * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets - */ - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT); } return WINED3D_OK; } @@ -7100,8 +6602,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice * || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) { surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED); } else { - ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); - surface_load_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); + struct wined3d_context *context = ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); + surface_load_ds_location(This->stencilBufferTarget, context, SFLAG_DS_OFFSCREEN); surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); } } @@ -7135,7 +6637,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i /* some basic validation checks */ if(This->cursorTexture) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glDeleteTextures(1, &This->cursorTexture); LEAVE_GL(); @@ -7185,7 +6687,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i INT height = This->cursorHeight; INT width = This->cursorWidth; INT bpp = glDesc->byte_count; - INT i, sampler; + DWORD sampler; + INT i; /* Reformat the texture memory (pitch and width can be * different) */ @@ -7193,6 +6696,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i for(i = 0; i < height; i++) memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp); IWineD3DSurface_UnlockRect(pCursorBitmap); + + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { @@ -7204,7 +6710,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); checkGLcall("glActiveTextureARB"); sampler = This->rev_tex_unit_map[0]; - if (sampler != -1) { + if (sampler != WINED3D_UNMAPPED_STAGE) + { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler)); } /* Create a new cursor texture */ @@ -7341,14 +6848,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* return WINED3DERR_DRIVERINTERNALERROR; } +static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) { + TRACE("checking resource %p for eviction\n", resource); + if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) { + TRACE("Evicting %p\n", resource); + IWineD3DResource_UnLoad(resource); + } + IWineD3DResource_Release(resource); + return S_OK; +} static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - /** FIXME: Resource tracking needs to be done, - * The closes we can do to this is set the priorities of all managed textures low - * and then reset them. - ***********************************************************/ - FIXME("(%p) : stub\n", This); + TRACE("(%p)\n", This); + + IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL); return WINED3D_OK; } @@ -7383,12 +6897,13 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT surface->glRect.right = surface->pow2Width; surface->glRect.bottom = surface->pow2Height; - if(surface->glDescription.textureName) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if (surface->texture_name) + { + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); - glDeleteTextures(1, &surface->glDescription.textureName); + glDeleteTextures(1, &surface->texture_name); LEAVE_GL(); - surface->glDescription.textureName = 0; + surface->texture_name = 0; surface->Flags &= ~SFLAG_CLIENT; } if(surface->pow2Width != pPresentationParameters->BackBufferWidth || @@ -7449,6 +6964,8 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_ UINT i; IWineD3DBaseShaderImpl *shader; + ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + 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); @@ -7483,7 +7000,6 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_ while(This->numContexts) { DestroyContext(This, This->contexts[0]); } - This->activeContext = NULL; HeapFree(GetProcessHeap(), 0, swapchain->context); swapchain->context = NULL; swapchain->num_contexts = 0; @@ -7505,7 +7021,6 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain * 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); @@ -7775,69 +7290,36 @@ static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT i * 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 IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){ - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; +void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource) +{ + TRACE("(%p) : Adding resource %p\n", This, resource); - TRACE("(%p) : Adding Resource %p\n", This, resource); list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry); } -static void IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){ - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - +static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource) +{ TRACE("(%p) : Removing resource %p\n", This, resource); list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry); } - -static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){ - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; +void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource) +{ WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource); int counter; TRACE("(%p) : resource %p\n", This, resource); - context_resource_released(iface, resource, type); + context_resource_released((IWineD3DDevice *)This, resource, type); switch (type) { /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */ case WINED3DRTYPE_SURFACE: { unsigned int i; - /* Cleanup any FBO attachments if d3d is enabled */ - if(This->d3d_initialized) { - if((IWineD3DSurface *)resource == This->lastActiveRenderTarget) { - IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL; - - TRACE("Last active render target destroyed\n"); - /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL - * checks, so switch to a valid target as long as the currently set surface is still valid. Use the - * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed - * and the lastActiveRenderTarget member shouldn't matter - */ - if(swapchain) { - if(swapchain->backBuffer && swapchain->backBuffer[0] != (IWineD3DSurface *)resource) { - TRACE("Activating primary back buffer\n"); - ActivateContext(This, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD); - } else if(!swapchain->backBuffer && swapchain->frontBuffer != (IWineD3DSurface *)resource) { - /* Single buffering environment */ - TRACE("Activating primary front buffer\n"); - ActivateContext(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD); - } else { - TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n"); - /* Implicit render target destroyed, that means the device is being destroyed - * whatever we set here, it shouldn't matter - */ - This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe; - } - } else { - /* May happen during ddraw uninitialization */ - TRACE("Render target set, but swapchain does not exist!\n"); - This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe; - } - } - + if (This->d3d_initialized) + { for (i = 0; i < GL_LIMITS(buffers); ++i) { if (This->render_targets[i] == (IWineD3DSurface *)resource) { This->render_targets[i] = NULL; @@ -7913,7 +7395,7 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW /* Remove the resource from the resourceStore */ - IWineD3DDeviceImpl_RemoveResource(iface, resource); + device_resource_remove(This, resource); TRACE("Resource released\n"); @@ -8085,7 +7567,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_UpdateSurface, IWineD3DDeviceImpl_GetFrontBufferData, /*** object tracking ***/ - IWineD3DDeviceImpl_ResourceReleased, IWineD3DDeviceImpl_EnumResources }; @@ -8209,12 +7690,11 @@ const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = { void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { DWORD rep = This->StateTable[state].representative; + struct wined3d_context *context; DWORD idx; BYTE shift; UINT i; - WineD3DContext *context; - if(!rep) return; for(i = 0; i < This->numContexts; i++) { context = This->contexts[i]; if(isStateDirty(context, rep)) continue; @@ -8226,28 +7706,29 @@ void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { } } -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_pbuffer(struct wined3d_context *context, UINT *width, UINT *height) +{ + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.wineD3DDevice; + /* The drawable size of a pbuffer render target is the current pbuffer size. */ + *width = device->pbufferWidth; + *height = device->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_fbo(struct wined3d_context *context, UINT *width, UINT *height) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->current_rt; + /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */ + *width = surface->pow2Width; + *height = surface->pow2Height; } -void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { - IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice; +void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->surface; /* 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; + * surface the context belongs to. */ + *width = surface->currentDesc.Width; + *height = surface->currentDesc.Height; } diff --git a/reactos/dll/directx/wine/wined3d/directx.c b/reactos/dll/directx/wine/wined3d/directx.c index 9a064bb996e..d9608f517a5 100644 --- a/reactos/dll/directx/wine/wined3d/directx.c +++ b/reactos/dll/directx/wine/wined3d/directx.c @@ -22,15 +22,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -/* Compile time diagnostics: */ - -#ifndef DEBUG_SINGLE_MODE -/* Set to 1 to force only a single display mode to be exposed: */ -#define DEBUG_SINGLE_MODE 0 -#endif - #include "config.h" -#include #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); @@ -63,6 +55,9 @@ static const struct { /* ARB */ {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 }, + {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 }, + {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 }, + {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 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 }, @@ -103,8 +98,10 @@ static const struct { {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 }, {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 }, {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 }, + {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 }, {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 }, {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 }, + {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 }, {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 }, {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 }, {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 }, @@ -140,7 +137,9 @@ static const struct { {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 }, {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 }, {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 }, + {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 }, {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 }, + {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 }, {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 }, {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 }, @@ -171,19 +170,40 @@ const int maxLookup[MAX_LOOKUPS] = DWORD *stateLookup[MAX_LOOKUPS]; -struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1]; -const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] = +const struct min_lookup minMipLookup[] = { - {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, - {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, - {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, - {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/ + {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */ }; -GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1]; -const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] = +const struct min_lookup minMipLookup_noFilter[] = { - GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */ +}; + +const struct min_lookup minMipLookup_noMip[] = +{ + /* NONE POINT LINEAR */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */ + {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */ + {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */ +}; + +const GLenum magLookup[] = +{ + /* NONE POINT LINEAR */ + GL_NEAREST, GL_NEAREST, GL_LINEAR, +}; + +const GLenum magLookup_noFilter[] = +{ + /* NONE POINT LINEAR */ + GL_NEAREST, GL_NEAREST, GL_NEAREST, }; /* drawStridedSlow attributes */ @@ -200,132 +220,104 @@ glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT]; * function query some info from GL. */ -static int wined3d_fake_gl_context_ref = 0; -static BOOL wined3d_fake_gl_context_foreign; -static BOOL wined3d_fake_gl_context_available = FALSE; -static HDC wined3d_fake_gl_context_hdc = NULL; -static HWND wined3d_fake_gl_context_hwnd = NULL; - -static CRITICAL_SECTION wined3d_fake_gl_context_cs; -static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug = +struct wined3d_fake_gl_ctx { - 0, 0, &wined3d_fake_gl_context_cs, - { &wined3d_fake_gl_context_cs_debug.ProcessLocksList, - &wined3d_fake_gl_context_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") } + HDC dc; + HWND wnd; + HGLRC gl_ctx; }; -static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 }; -static void WineD3D_ReleaseFakeGLContext(void) { - HGLRC glCtx; +static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx) +{ + TRACE_(d3d_caps)("Destroying fake GL context.\n"); - EnterCriticalSection(&wined3d_fake_gl_context_cs); - - if(!wined3d_fake_gl_context_available) { - TRACE_(d3d_caps)("context not available\n"); - LeaveCriticalSection(&wined3d_fake_gl_context_cs); - return; + if (!pwglMakeCurrent(NULL, NULL)) + { + ERR_(d3d_caps)("Failed to disable fake GL context.\n"); } - glCtx = pwglGetCurrentContext(); - - TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref); - if (0 == (--wined3d_fake_gl_context_ref) ) { - if(!wined3d_fake_gl_context_foreign && glCtx) { - TRACE_(d3d_caps)("destroying fake GL context\n"); - pwglMakeCurrent(NULL, NULL); - //pwglDeleteContext(glCtx); - } - if(wined3d_fake_gl_context_hdc) - ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc); - wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */ - if(wined3d_fake_gl_context_hwnd) - DestroyWindow(wined3d_fake_gl_context_hwnd); - wined3d_fake_gl_context_hwnd = NULL; - wined3d_fake_gl_context_available = FALSE; + if (!pwglDeleteContext(ctx->gl_ctx)) + { + DWORD err = GetLastError(); + ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err); } - assert(wined3d_fake_gl_context_ref >= 0); - LeaveCriticalSection(&wined3d_fake_gl_context_cs); + ReleaseDC(ctx->wnd, ctx->dc); + DestroyWindow(ctx->wnd); } -static BOOL WineD3D_CreateFakeGLContext(void) { - HGLRC glCtx = NULL; - - EnterCriticalSection(&wined3d_fake_gl_context_cs); +static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx) +{ + PIXELFORMATDESCRIPTOR pfd; + int iPixelFormat; TRACE("getting context...\n"); - if(wined3d_fake_gl_context_ref > 0) goto ret; - assert(0 == wined3d_fake_gl_context_ref); - wined3d_fake_gl_context_foreign = TRUE; - - glCtx = pwglGetCurrentContext(); - if (!glCtx) { - PIXELFORMATDESCRIPTOR pfd; - int iPixelFormat; - - wined3d_fake_gl_context_foreign = FALSE; - - /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */ - wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL); - if(!wined3d_fake_gl_context_hwnd) { - ERR("HWND creation failed!\n"); - goto fail; - } - wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd); - if(!wined3d_fake_gl_context_hdc) { - ERR("GetDC failed!\n"); - goto fail; - } - - /* 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.cColorBits = 32; - pfd.iLayerType = PFD_MAIN_PLANE; - - iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd); - if(!iPixelFormat) { - /* If this happens something is very wrong as ChoosePixelFormat barely fails */ - ERR("Can't find a suitable iPixelFormat\n"); - goto fail; - } - DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd); - SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd); - - /* Create a GL context */ - glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc); - if (!glCtx) { - WARN_(d3d_caps)("Error creating default context for capabilities initialization\n"); - goto fail; - } - - /* Make it the current GL context */ - if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) { - WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n"); - goto fail; - } + /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */ + ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window", + WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL); + if (!ctx->wnd) + { + ERR_(d3d_caps)("Failed to create a window.\n"); + goto fail; + } + + ctx->dc = GetDC(ctx->wnd); + if (!ctx->dc) + { + ERR_(d3d_caps)("Failed to get a DC.\n"); + goto fail; + } + + /* 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.cColorBits = 32; + pfd.iLayerType = PFD_MAIN_PLANE; + + iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd); + if (!iPixelFormat) + { + /* If this happens something is very wrong as ChoosePixelFormat barely fails. */ + ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n"); + goto fail; + } + DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd); + SetPixelFormat(ctx->dc, iPixelFormat, &pfd); + + /* Create a GL context. */ + ctx->gl_ctx = pwglCreateContext(ctx->dc); + if (!ctx->gl_ctx) + { + WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n"); + goto fail; + } + + /* Make it the current GL context. */ + if (!context_set_current(NULL)) + { + ERR_(d3d_caps)("Failed to clear current D3D context.\n"); + } + + if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx)) + { + ERR_(d3d_caps)("Failed to make fake GL context current.\n"); + goto fail; } - ret: - TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref); - wined3d_fake_gl_context_ref++; - wined3d_fake_gl_context_available = TRUE; - LeaveCriticalSection(&wined3d_fake_gl_context_cs); return TRUE; - fail: - if(wined3d_fake_gl_context_hdc) - ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc); - wined3d_fake_gl_context_hdc = NULL; - if(wined3d_fake_gl_context_hwnd) - DestroyWindow(wined3d_fake_gl_context_hwnd); - wined3d_fake_gl_context_hwnd = NULL; - if(glCtx) pwglDeleteContext(glCtx); - LeaveCriticalSection(&wined3d_fake_gl_context_cs); + +fail: + if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx); + ctx->gl_ctx = NULL; + if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc); + ctx->dc = NULL; + if (ctx->wnd) DestroyWindow(ctx->wnd); + ctx->wnd = NULL; + return FALSE; } @@ -387,7 +379,8 @@ 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(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected) +static void select_shader_mode(const struct wined3d_gl_info *gl_info, + WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected) { if (wined3d_settings.vs_mode == VS_NONE) { *vs_selected = SHADER_NONE; @@ -395,7 +388,7 @@ static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE De /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB * shaders only on this card. */ - if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20) + if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2]) *vs_selected = SHADER_ARB; else *vs_selected = SHADER_GLSL; @@ -419,11 +412,8 @@ static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE De } /** Select the number of report maximum shader constants based on the selected shader modes */ -static void select_shader_max_constants( - int ps_selected_mode, - int vs_selected_mode, - WineD3D_GL_Info *gl_info) { - +static void select_shader_max_constants(int ps_selected_mode, int vs_selected_mode, struct wined3d_gl_info *gl_info) +{ switch (vs_selected_mode) { case SHADER_GLSL: gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF; @@ -453,7 +443,8 @@ static void select_shader_max_constants( * IWineD3D parts follows **********************************************************/ -static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info) +/* GL locking is done by the caller */ +static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info) { GLuint prog; BOOL ret = FALSE; @@ -482,7 +473,7 @@ static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info) GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0)); GL_EXTCALL(glDeleteProgramsARB(1, &prog)); - checkGLcall("ARB vp offset limit test cleanup\n"); + checkGLcall("ARB vp offset limit test cleanup"); return ret; } @@ -498,208 +489,1032 @@ static DWORD ver_for_ext(GL_SupportedExt ext) return 0; } -static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { +static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + if (gl_info->gl_vendor != VENDOR_ATI) return FALSE; + if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE; + if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE; + if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE; + return FALSE; +} + +static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + if (gl_info->gl_vendor == VENDOR_NVIDIA) + { + if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) + { + return TRUE; + } + } + return FALSE; +} + +static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from + * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to + * detect the Apple OpenGL implementation to apply some extension fixups afterwards. + * + * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks + * 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 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] + && gl_info->supported[APPLE_CLIENT_STORAGE] + && gl_info->supported[APPLE_FLUSH_RENDER] + && gl_info->supported[APPLE_YCBCR_422]) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/* Context activation is done by the caller. */ +static void test_pbo_functionality(struct 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])]; + + /* No PBO -> No point in testing them. */ + if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return; + + ENTER_GL(); + + while (glGetError()); + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + 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"); + + 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"); + + 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"); + + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + wglFinish(); /* 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"); + + glDeleteTextures(1, &texture); + GL_EXTCALL(glDeleteBuffersARB(1, &pbo)); + checkGLcall("PBO test cleanup"); + + LEAVE_GL(); + + if (memcmp(check, pattern, sizeof(check))) + { + 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"); + } +} + +static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer); +} + +static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + if (!match_apple(gl_info, gl_renderer)) return FALSE; + if (gl_info->gl_vendor != VENDOR_ATI) return FALSE; + if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE; + return TRUE; +} + +static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + if (gl_info->gl_vendor != VENDOR_ATI) return FALSE; + if (match_apple(gl_info, gl_renderer)) return FALSE; + if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */ + return TRUE; +} + +static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports + * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card. + * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44 + * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is + * hardcoded + * + * dx10 cards usually have 64 varyings */ + return gl_info->max_glsl_varyings > 44; +} + +/* A GL context is provided by the caller */ +static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + GLenum error; + DWORD data[16]; + + if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE; + + ENTER_GL(); + while(glGetError()); + GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data); + error = glGetError(); + LEAVE_GL(); + + if(error == GL_NO_ERROR) + { + TRACE("GL Implementation accepts 4 component specular color pointers\n"); + return TRUE; + } + else + { + TRACE("GL implementation does not accept 4 component specular colors, error %s\n", + debug_glerror(error)); + return FALSE; + } +} + +static void quirk_arb_constants(struct wined3d_gl_info *gl_info) +{ + TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF); + gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF; + TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF); + gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF; +} + +static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info) +{ + quirk_arb_constants(gl_info); + /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms. + * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should + * allow 48 different offsets or other helper immediate values. */ + TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n"); + gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12); +} + +/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB + * on more than one texture unit. This means that the d3d9 visual point size test will cause a + * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This + * quirk only enables point sprites on the first texture unit. This keeps point sprites working in + * most games, but avoids the crash + * + * A more sophisticated way would be to find all units that need texture coordinates and enable + * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow + * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though) + * + * Note that disabling the extension entirely does not gain predictability because there is no point + * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */ +static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info) +{ + if (gl_info->supported[ARB_POINT_SPRITE]) + { + TRACE("Limiting point sprites to one texture unit.\n"); + gl_info->max_point_sprite_units = 1; + } +} + +static void quirk_ati_dx9(struct wined3d_gl_info *gl_info) +{ + quirk_arb_constants(gl_info); + + /* 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]) + { + 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; + } + + /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although + * it is generally more efficient. Reserve just 8 constants. */ + TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n"); + gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8); +} + +static void quirk_no_np2(struct wined3d_gl_info *gl_info) +{ + /* 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. */ + 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; +} + +static void quirk_texcoord_w(struct wined3d_gl_info *gl_info) +{ + /* 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. */ + TRACE("Enabling vertex texture coord fixes in vertex shaders.\n"); + gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W; +} + +static void quirk_clip_varying(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING; +} + +static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info) +{ + gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA; +} + +struct driver_quirk +{ + BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer); + void (*apply)(struct wined3d_gl_info *gl_info); + const char *description; +}; + +struct driver_quirk quirk_table[] = +{ + { + match_ati_r300_to_500, + quirk_ati_dx9, + "ATI GLSL constant and normalized texrect quirk" + }, + /* 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. + * + * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */ + { + match_apple, + quirk_apple_glsl_constants, + "Apple GLSL uniform override" + }, + { + match_geforce5, + quirk_no_np2, + "Geforce 5 NP2 disable" + }, + { + match_apple_intel, + quirk_texcoord_w, + "Init texcoord .w for Apple Intel GPU driver" + }, + { + match_apple_nonr500ati, + quirk_texcoord_w, + "Init texcoord .w for Apple ATI >= r600 GPU driver" + }, + { + match_fglrx, + quirk_one_point_sprite, + "Fglrx point sprite crash workaround" + }, + { + match_dx10_capable, + quirk_clip_varying, + "Reserved varying for gl_ClipPos" + }, + { + /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most + * GL implementations accept it. The Mac GL is the only implementation known to + * reject it. + * + * If we can pass 4 component specular colors, do it, because (a) we don't have + * to screw around with the data, and (b) the D3D fixed function vertex pipeline + * passes specular alpha to the pixel shader if any is used. Otherwise the + * specular alpha is used to pass the fog coordinate, which we pass to opengl + * via GL_EXT_fog_coord. + */ + match_allows_spec_alpha, + quirk_allows_specular_alpha, + "Allow specular alpha quirk" + } +}; + +/* 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 */ + const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */ + 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 (180.x) + * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown + * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89 + * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86 + * + * All version numbers used below are from the Linux nvidia drivers. */ + {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 }, + + /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */ + {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 }, + + /* TODO: Add information about legacy ATI hardware, Intel and other cards. */ +}; + +/* Context activation is done by the caller. */ +static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer) +{ + unsigned int i; + + for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i) + { + if (!quirk_table[i].match(gl_info, gl_renderer)) continue; + TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description); + quirk_table[i].apply(gl_info); + } + + /* Find out if PBOs work as they are supposed to. */ + test_pbo_functionality(gl_info); + + /* Fixup the driver version we'll report to the app. */ + gl_info->driver_version = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */ + gl_info->driver_version_hipart = MAKEDWORD_VERSION(7, 1); + 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); + gl_info->driver_description = driver_version_table[i].description; + break; + } + } + TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08X-0x%08X.\n", + gl_info->driver_version_hipart, gl_info->driver_version); +} + +static DWORD wined3d_parse_gl_version(const char *gl_version) +{ + const char *ptr = gl_version; + int major, minor; + + major = atoi(ptr); + if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major); + + while (isdigit(*ptr)) ++ptr; + if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version)); + + minor = atoi(ptr); + + TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor); + + return MAKEDWORD_VERSION(major, minor); +} + +static GL_Vendors wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer) +{ + if (strstr(gl_vendor, "NVIDIA")) + return VENDOR_NVIDIA; + + if (strstr(gl_vendor, "ATI")) + return VENDOR_ATI; + + if (strstr(gl_vendor, "Intel(R)") + || strstr(gl_renderer, "Intel(R)") + || strstr(gl_vendor, "Intel Inc.")) + return VENDOR_INTEL; + + if (strstr(gl_vendor, "Mesa") + || strstr(gl_vendor, "Tungsten Graphics, Inc.")) + return VENDOR_MESA; + + FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor)); + + return VENDOR_WINE; +} + +static GL_Cards wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer, + GL_Vendors *vendor, unsigned int *vidmem) +{ + /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of + * different GPUs with roughly the same features. In most cases GPUs from a + * certain family differ in clockspeeds, the amount of video memory and the + * number of shader pipelines. + * + * A Direct3D device object contains the PCI id (vendor + device) of the + * videocard which is used for rendering. Various applications use this + * information to get a rough estimation of the features of the card and + * some might use it for enabling 3d effects only on certain types of + * videocards. In some cases games might even use it to work around bugs + * which happen on certain videocards/driver combinations. The problem is + * that OpenGL only exposes a rendering string containing the name of the + * videocard and not the PCI id. + * + * Various games depend on the PCI id, so somehow we need to provide one. + * A simple option is to parse the renderer string and translate this to + * the right PCI id. This is a lot of work because there are more than 200 + * GPUs just for Nvidia. Various cards share the same renderer string, so + * the amount of code might be 'small' but there are quite a number of + * exceptions which would make this a pain to maintain. Another way would + * be to query the PCI id from the operating system (assuming this is the + * videocard which is used for rendering which is not always the case). + * This would work but it is not very portable. Second it would not work + * well in, let's say, a remote X situation in which the amount of 3d + * features which can be used is limited. + * + * As said most games only use the PCI id to get an indication of the + * capabilities of the card. It doesn't really matter if the given id is + * the correct one if we return the id of a card with similar 3d features. + * + * The code below checks the OpenGL capabilities of a videocard and matches + * that to a certain level of Direct3D functionality. Once a card passes + * the Direct3D9 check, we know that the card (in case of Nvidia) is at + * least a GeforceFX. To give a better estimate we do a basic check on the + * renderer string but if that won't pass we return a default card. This + * way is better than maintaining a full card database as even without a + * full database we can return a card with similar features. Second the + * size of the database can be made quite small because when you know what + * type of 3d functionality a card has, you know to which GPU family the + * GPU must belong. Because of this you only have to check a small part of + * the renderer string to distinguishes between different models from that + * family. + * + * The code also selects a default amount of video memory which we will + * use for an estimation of the amount of free texture memory. In case of + * real D3D the amount of texture memory includes video memory and system + * memory (to be specific AGP memory or in case of PCIE TurboCache / + * HyperMemory). We don't know how much system memory can be addressed by + * the system but we can make a reasonable estimation about the amount of + * 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 amount of video + * memory can be overruled using a registry setting. */ + + switch (*vendor) + { + case VENDOR_NVIDIA: + /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more + * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. + */ + if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3]) + { + /* Geforce 200 - highend */ + if (strstr(gl_renderer, "GTX 280") + || strstr(gl_renderer, "GTX 285") + || strstr(gl_renderer, "GTX 295")) + { + *vidmem = 1024; + return CARD_NVIDIA_GEFORCE_GTX280; + } + + /* Geforce 200 - midend high */ + if (strstr(gl_renderer, "GTX 275")) + { + *vidmem = 896; + return CARD_NVIDIA_GEFORCE_GTX275; + } + + /* Geforce 200 - midend */ + if (strstr(gl_renderer, "GTX 260")) + { + *vidmem = 1024; + return CARD_NVIDIA_GEFORCE_GTX260; + } + + /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */ + if (strstr(gl_renderer, "9800") + || strstr(gl_renderer, "GTS 150") + || strstr(gl_renderer, "GTS 250")) + { + *vidmem = 512; + return CARD_NVIDIA_GEFORCE_9800GT; + } + + /* Geforce9 - midend */ + if (strstr(gl_renderer, "9600")) + { + *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */ + return CARD_NVIDIA_GEFORCE_9600GT; + } + + /* Geforce9 - midend low / Geforce 200 - low */ + if (strstr(gl_renderer, "9500") + || strstr(gl_renderer, "GT 120") + || strstr(gl_renderer, "GT 130")) + { + *vidmem = 256; /* The 9500GT has 256-1024MB */ + return CARD_NVIDIA_GEFORCE_9500GT; + } + + /* Geforce9 - lowend */ + if (strstr(gl_renderer, "9400")) + { + *vidmem = 256; /* The 9400GT has 256-1024MB */ + return CARD_NVIDIA_GEFORCE_9400GT; + } + + /* Geforce9 - lowend low */ + if (strstr(gl_renderer, "9100") + || strstr(gl_renderer, "9200") + || strstr(gl_renderer, "9300") + || strstr(gl_renderer, "G 100")) + { + *vidmem = 256; /* The 9100-9300 cards have 256MB */ + return CARD_NVIDIA_GEFORCE_9200; + } + + /* Geforce8 - highend */ + if (strstr(gl_renderer, "8800")) + { + *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */ + return CARD_NVIDIA_GEFORCE_8800GTS; + } + + /* Geforce8 - midend mobile */ + if (strstr(gl_renderer, "8600 M")) + { + *vidmem = 512; + return CARD_NVIDIA_GEFORCE_8600MGT; + } + + /* Geforce8 - midend */ + if (strstr(gl_renderer, "8600") + || strstr(gl_renderer, "8700")) + { + *vidmem = 256; + return CARD_NVIDIA_GEFORCE_8600GT; + } + + /* Geforce8 - lowend */ + if (strstr(gl_renderer, "8300") + || strstr(gl_renderer, "8400") + || strstr(gl_renderer, "8500")) + { + *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */ + return CARD_NVIDIA_GEFORCE_8300GS; + } + + /* Geforce7 - highend */ + if (strstr(gl_renderer, "7800") + || strstr(gl_renderer, "7900") + || strstr(gl_renderer, "7950") + || strstr(gl_renderer, "Quadro FX 4") + || strstr(gl_renderer, "Quadro FX 5")) + { + *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */ + return CARD_NVIDIA_GEFORCE_7800GT; + } + + /* Geforce7 midend */ + if (strstr(gl_renderer, "7600") + || strstr(gl_renderer, "7700")) + { + *vidmem = 256; /* The 7600 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_7600; + } + + /* Geforce7 lower medium */ + if (strstr(gl_renderer, "7400")) + { + *vidmem = 256; /* The 7400 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_7400; + } + + /* Geforce7 lowend */ + if (strstr(gl_renderer, "7300")) + { + *vidmem = 256; /* Mac Pros with this card have 256 MB */ + return CARD_NVIDIA_GEFORCE_7300; + } + + /* Geforce6 highend */ + if (strstr(gl_renderer, "6800")) + { + *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */ + return CARD_NVIDIA_GEFORCE_6800; + } + + /* Geforce6 - midend */ + if (strstr(gl_renderer, "6600") + || strstr(gl_renderer, "6610") + || strstr(gl_renderer, "6700")) + { + *vidmem = 128; /* A 6600GT has 128-256MB */ + return CARD_NVIDIA_GEFORCE_6600GT; + } + + /* Geforce6/7 lowend */ + *vidmem = 64; /* */ + return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */ + } + + if (WINE_D3D9_CAPABLE(gl_info)) + { + /* GeforceFX - highend */ + if (strstr(gl_renderer, "5800") + || strstr(gl_renderer, "5900") + || strstr(gl_renderer, "5950") + || strstr(gl_renderer, "Quadro FX")) + { + *vidmem = 256; /* 5800-5900 cards use 256MB */ + return CARD_NVIDIA_GEFORCEFX_5800; + } + + /* GeforceFX - midend */ + if (strstr(gl_renderer, "5600") + || strstr(gl_renderer, "5650") + || strstr(gl_renderer, "5700") + || strstr(gl_renderer, "5750")) + { + *vidmem = 128; /* A 5600 uses 128-256MB */ + return CARD_NVIDIA_GEFORCEFX_5600; + } + + /* GeforceFX - lowend */ + *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */ + return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */ + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4")) + { + *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */ + return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */ + } + + *vidmem = 64; /* Geforce3 cards have 64-128MB */ + return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */ + } + + if (WINE_D3D7_CAPABLE(gl_info)) + { + if (strstr(gl_renderer, "GeForce4 MX")) + { + /* Most Geforce4MX GPUs have at least 64MB of memory, some + * early models had 32MB but most have 64MB or even 128MB. */ + *vidmem = 64; + return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */ + } + + if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR")) + { + *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */ + return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */ + } + + if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2")) + { + *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */ + return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */ + } + + /* Most Geforce1 cards have 32MB, there are also some rare 16 + * and 64MB (Dell) models. */ + *vidmem = 32; + return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */ + } + + if (strstr(gl_renderer, "TNT2")) + { + *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */ + return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */ + } + + *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */ + return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */ + + case VENDOR_ATI: + /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx + * + * Beware: renderer string do not match exact card model, + * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */ + if (WINE_D3D9_CAPABLE(gl_info)) + { + /* Radeon R7xx HD4800 - highend */ + if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */ + || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */ + { + *vidmem = 512; /* note: HD4890 cards use 1024MB */ + return CARD_ATI_RADEON_HD4800; + } + + /* Radeon R740 HD4700 - midend */ + if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */ + || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4700; + } + + /* Radeon R730 HD4600 - midend */ + if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */ + || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */ + || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */ + { + *vidmem = 512; + return CARD_ATI_RADEON_HD4600; + } + + /* Radeon R710 HD4500/HD4350 - lowend */ + if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */ + || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */ + { + *vidmem = 256; + return CARD_ATI_RADEON_HD4350; + } + + /* Radeon R6xx HD2900/HD3800 - highend */ + if (strstr(gl_renderer, "HD 2900") + || strstr(gl_renderer, "HD 3870") + || strstr(gl_renderer, "HD 3850")) + { + *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */ + return CARD_ATI_RADEON_HD2900; + } + + /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */ + if (strstr(gl_renderer, "HD 2600") + || strstr(gl_renderer, "HD 3830") + || strstr(gl_renderer, "HD 3690") + || strstr(gl_renderer, "HD 3650")) + { + *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */ + return CARD_ATI_RADEON_HD2600; + } + + /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */ + if (strstr(gl_renderer, "HD 2300") + || strstr(gl_renderer, "HD 2400") + || strstr(gl_renderer, "HD 3470") + || strstr(gl_renderer, "HD 3450") + || strstr(gl_renderer, "HD 3430") + || strstr(gl_renderer, "HD 3400")) + { + *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ + return CARD_ATI_RADEON_HD2300; + } + + /* Radeon R6xx/R7xx integrated */ + if (strstr(gl_renderer, "HD 3100") + || strstr(gl_renderer, "HD 3200") + || strstr(gl_renderer, "HD 3300")) + { + *vidmem = 128; /* 128MB */ + return CARD_ATI_RADEON_HD3200; + } + + /* Radeon R5xx */ + if (strstr(gl_renderer, "X1600") + || strstr(gl_renderer, "X1650") + || strstr(gl_renderer, "X1800") + || strstr(gl_renderer, "X1900") + || strstr(gl_renderer, "X1950")) + { + *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */ + return CARD_ATI_RADEON_X1600; + } + + /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */ + if (strstr(gl_renderer, "X700") + || strstr(gl_renderer, "X800") + || strstr(gl_renderer, "X850") + || strstr(gl_renderer, "X1300") + || strstr(gl_renderer, "X1400") + || strstr(gl_renderer, "X1450") + || strstr(gl_renderer, "X1550")) + { + *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */ + return CARD_ATI_RADEON_X700; + } + + /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */ + if (strstr(gl_renderer, "Radeon Xpress")) + { + *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */ + return CARD_ATI_RADEON_XPRESS_200M; + } + + /* Radeon R3xx */ + *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */ + return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */ + } + + if (WINE_D3D8_CAPABLE(gl_info)) + { + *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */ + return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */ + } + + if (WINE_D3D7_CAPABLE(gl_info)) + { + *vidmem = 32; /* There are models with up to 64MB */ + return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */ + } + + *vidmem = 16; /* There are 16-32MB models */ + return CARD_ATI_RAGE_128PRO; + + case VENDOR_INTEL: + if (strstr(gl_renderer, "X3100")) + { + /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */ + *vidmem = 128; + return CARD_INTEL_X3100; + } + + if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM")) + { + /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */ + *vidmem = 64; + return CARD_INTEL_I945GM; + } + + if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM; + if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G; + if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G; + if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G; + if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G; + return CARD_INTEL_I915G; + + case VENDOR_MESA: + case VENDOR_WINE: + default: + /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice + * for Nvidia was because the hardware and drivers they make are of good quality. This makes + * them a good generic choice. */ + *vendor = VENDOR_NVIDIA; + if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600; + if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3; + if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE; + if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT; + return CARD_NVIDIA_RIVA_128; + } +} + +/* Context activation is done by the caller. */ +static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_gl_info *gl_info) +{ const char *GL_Extensions = NULL; const char *WGL_Extensions = NULL; const char *gl_string = NULL; - const char *gl_string_cursor = NULL; GLint gl_max; GLfloat gl_floatv[2]; - int major = 1, minor = 0; - BOOL return_value = TRUE; unsigned i; HDC hdc; unsigned int vidmem=0; + char *gl_renderer; + DWORD gl_version; + size_t len; TRACE_(d3d_caps)("(%p)\n", gl_info); ENTER_GL(); - gl_string = (const char *) glGetString(GL_RENDERER); - if (!gl_string) gl_string = "None"; - strcpy(gl_info->gl_renderer, gl_string); - - gl_string = (const char *) glGetString(GL_VENDOR); - TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string); - if (gl_string != NULL) { - /* Fill in the GL vendor */ - if (strstr(gl_string, "NVIDIA")) { - 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)") || - strstr(gl_string, "Intel Inc.")) { - gl_info->gl_vendor = VENDOR_INTEL; - } else if (strstr(gl_string, "Mesa")) { - gl_info->gl_vendor = VENDOR_MESA; - } else { - gl_info->gl_vendor = VENDOR_WINE; - } - } else { - gl_info->gl_vendor = VENDOR_WINE; + gl_string = (const char *)glGetString(GL_RENDERER); + TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string)); + if (!gl_string) + { + ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n"); + return FALSE; } + len = strlen(gl_string) + 1; + gl_renderer = HeapAlloc(GetProcessHeap(), 0, len); + if (!gl_renderer) + { + ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n"); + return FALSE; + } + memcpy(gl_renderer, gl_string, len); + gl_string = (const char *)glGetString(GL_VENDOR); + TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string)); + if (!gl_string) + { + ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n"); + HeapFree(GetProcessHeap(), 0, gl_renderer); + return FALSE; + } + gl_info->gl_vendor = wined3d_guess_vendor(gl_string, gl_renderer); TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor); /* Parse the GL_VERSION field into major and minor information */ - 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"); - if (!gl_string_cursor) { - ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string)); - break; - } - - gl_string_cursor = strstr(gl_string_cursor, " "); - if (!gl_string_cursor) { - ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string)); - break; - } - - while (*gl_string_cursor == ' ') { - ++gl_string_cursor; - } - - if (!*gl_string_cursor) { - ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string)); - break; - } - - 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 nVidia version string: %s\n", debugstr_a(gl_string)); - break; - } - - minor = atoi(gl_string_cursor); - minor = major*100+minor; - major = 10; - - break; - - case VENDOR_ATI: - major = minor = 0; - gl_string_cursor = strchr(gl_string, '-'); - if (gl_string_cursor) { - int error = 0; - gl_string_cursor++; - - /* Check if version number is of the form x.y.z */ - if (*gl_string_cursor > '9' && *gl_string_cursor < '0') - error = 1; - if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0') - error = 1; - if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0') - error = 1; - if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.') - error = 1; - - /* Mark version number as malformed */ - if (error) - gl_string_cursor = 0; - } - - if (!gl_string_cursor) - WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string)); - else { - major = *gl_string_cursor - '0'; - minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0'); - } - break; - - 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, " "); - while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor; - if (*gl_string_cursor) { - char tmp[16]; - int cursor = 0; - - while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') { - tmp[cursor++] = *gl_string_cursor; - ++gl_string_cursor; - } - tmp[cursor] = 0; - major = atoi(tmp); - - if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string)); - ++gl_string_cursor; - - cursor = 0; - while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') { - tmp[cursor++] = *gl_string_cursor; - ++gl_string_cursor; - } - tmp[cursor] = 0; - minor = atoi(tmp); - } - break; - - default: - major = 0; - minor = 9; - } - 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); + gl_string = (const char *)glGetString(GL_VERSION); + TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string)); + if (!gl_string) + { + ERR_(d3d_caps)("Received a NULL GL_VERSION.\n"); + HeapFree(GetProcessHeap(), 0, gl_renderer); + return FALSE; } - - TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card); + gl_version = wined3d_parse_gl_version(gl_string); /* * Initialize openGL extension related variables @@ -713,18 +1528,15 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->max_vertex_samplers = 0; gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers; gl_info->max_sampler_stages = 1; - gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED; gl_info->ps_arb_max_temps = 0; gl_info->ps_arb_max_instructions = 0; - gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED; gl_info->vs_arb_max_temps = 0; gl_info->vs_arb_max_instructions = 0; - gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED; - gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED; gl_info->vs_glsl_constantsF = 0; gl_info->ps_glsl_constantsF = 0; gl_info->vs_arb_constantsF = 0; gl_info->ps_arb_constantsF = 0; + gl_info->ps_arb_max_local_constants = 0; /* Retrieve opengl defaults */ glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max); @@ -744,283 +1556,311 @@ static 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]); - /* Parse the gl supported features, in theory enabling parts of our code appropriately */ - GL_Extensions = (const char *) glGetString(GL_EXTENSIONS); + /* Parse the gl supported features, in theory enabling parts of our code appropriately. */ + GL_Extensions = (const char *)glGetString(GL_EXTENSIONS); + if (!GL_Extensions) + { + ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n"); + HeapFree(GetProcessHeap(), 0, gl_renderer); + return FALSE; + } + TRACE_(d3d_caps)("GL_Extensions reported:\n"); - if (NULL == GL_Extensions) { - ERR(" GL_Extensions returns NULL\n"); - } else { - while (*GL_Extensions != 0x00) { - const char *Start; - char ThisExtn[256]; - size_t len; + gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE; - while (isspace(*GL_Extensions)) GL_Extensions++; - Start = GL_Extensions; - while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) { - GL_Extensions++; - } + while (*GL_Extensions) + { + const char *start; + char current_ext[256]; - len = GL_Extensions - Start; - if (len == 0 || len >= sizeof(ThisExtn)) - continue; + while (isspace(*GL_Extensions)) ++GL_Extensions; + start = GL_Extensions; + while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions; - memcpy(ThisExtn, Start, len); - ThisExtn[len] = '\0'; - TRACE_(d3d_caps)("- %s\n", ThisExtn); + len = GL_Extensions - start; + if (!len || len >= sizeof(current_ext)) continue; - for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) { - if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) { - TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string); - gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; - break; - } - } - } + memcpy(current_ext, start, len); + current_ext[len] = '\0'; + TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext)); - 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_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \ - else gl_info->pfn = NULL; \ - } - GL_EXT_FUNCS_GEN; -#undef USE_GL_FUNC - -#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn); - 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_version && EXTENSION_MAP[i].version) { - TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string); + for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) + { + if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string)) + { + TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string); gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; + break; } } - - if (gl_info->supported[APPLE_FENCE]) { - /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically. - * The apple extension interacts with some other apple exts. Disable the NV - * extension if the apple one is support to prevent confusion in other parts - * of the code - */ - 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; - } - if (gl_info->supported[NV_TEXTURE_SHADER2]) { - 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); - gl_info->max_buffers = gl_max; - TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max); - } - if (gl_info->supported[ARB_MULTITEXTURE]) { - glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max); - gl_info->max_textures = min(MAX_TEXTURES, gl_max); - TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures); - - if (gl_info->supported[NV_REGISTER_COMBINERS]) { - GLint tmp; - glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp); - gl_info->max_texture_stages = min(MAX_TEXTURES, tmp); - } else { - gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max); - } - TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages); - - if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) { - GLint tmp; - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp); - gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp); - } else { - gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max); - } - TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers); - - if (gl_info->supported[ARB_VERTEX_SHADER]) { - GLint tmp; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp); - gl_info->max_vertex_samplers = tmp; - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp); - gl_info->max_combined_samplers = tmp; - - /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup - * is known at shader link time. In a vertex shader + pixel shader combination this isn't - * an issue because then the sampler setup only depends on the two shaders. If a pixel - * shader is used with fixed function vertex processing we're fine too because fixed function - * vertex processing doesn't use any samplers. If fixed function fragment processing is - * used we have to make sure that all vertex sampler setups are valid together with all - * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES - * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards). - * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and - * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have - * 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 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"); - 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; - } - TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers); - TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers); - } - if (gl_info->supported[ARB_VERTEX_BLEND]) { - glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max); - gl_info->max_blends = gl_max; - TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends); - } - if (gl_info->supported[EXT_TEXTURE3D]) { - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max); - gl_info->max_texture3d_size = gl_max; - TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size); - } - if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) { - glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max); - gl_info->max_anisotropy = gl_max; - TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy); - } - if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) { - gl_info->ps_arb_version = PS_VERSION_11; - GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); - gl_info->ps_arb_constantsF = gl_max; - TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF); - GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max)); - gl_info->ps_arb_max_temps = gl_max; - TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps); - GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max)); - gl_info->ps_arb_max_instructions = gl_max; - TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions); - } - if (gl_info->supported[ARB_VERTEX_PROGRAM]) { - gl_info->vs_arb_version = VS_VERSION_11; - GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); - gl_info->vs_arb_constantsF = gl_max; - TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF); - GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max)); - gl_info->vs_arb_max_temps = gl_max; - TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps); - GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max)); - gl_info->vs_arb_max_instructions = gl_max; - TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions); - - gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info); - } - if (gl_info->supported[ARB_VERTEX_SHADER]) { - glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max); - gl_info->vs_glsl_constantsF = gl_max / 4; - TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF); - } - if (gl_info->supported[ARB_FRAGMENT_SHADER]) { - glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max); - gl_info->ps_glsl_constantsF = gl_max / 4; - TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF); - glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max); - gl_info->max_glsl_varyings = gl_max; - TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4); - } - if (gl_info->supported[EXT_VERTEX_SHADER]) { - gl_info->vs_ati_version = VS_VERSION_11; - } - if (gl_info->supported[NV_VERTEX_PROGRAM3]) { - gl_info->vs_nv_version = VS_VERSION_30; - } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) { - gl_info->vs_nv_version = VS_VERSION_20; - } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) { - gl_info->vs_nv_version = VS_VERSION_11; - } else if (gl_info->supported[NV_VERTEX_PROGRAM]) { - gl_info->vs_nv_version = VS_VERSION_10; - } - if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) { - gl_info->ps_nv_version = PS_VERSION_30; - } 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; - } - if(gl_info->supported[NV_HALF_FLOAT]) { - /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */ - gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE; - } - if(gl_info->supported[ARB_POINT_SPRITE]) { - gl_info->max_point_sprite_units = gl_info->max_textures; - } else { - gl_info->max_point_sprite_units = 0; - } } - checkGLcall("extension detection\n"); + + 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_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \ + else gl_info->pfn = NULL; \ +} + GL_EXT_FUNCS_GEN; +#undef USE_GL_FUNC + +#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn); + 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] + && EXTENSION_MAP[i].version <= 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; + } + } + + if (gl_info->supported[APPLE_FENCE]) + { + /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically. + * The apple extension interacts with some other apple exts. Disable the NV + * extension if the apple one is support to prevent confusion in other parts + * of the code. */ + 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; + } + if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP]) + { + TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n"); + gl_info->supported[ARB_DEPTH_CLAMP] = TRUE; + } + if (gl_info->supported[NV_TEXTURE_SHADER2]) + { + 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); + gl_info->max_buffers = gl_max; + TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max); + } + if (gl_info->supported[ARB_MULTITEXTURE]) + { + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max); + gl_info->max_textures = min(MAX_TEXTURES, gl_max); + TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures); + + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + GLint tmp; + glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp); + gl_info->max_texture_stages = min(MAX_TEXTURES, tmp); + } + else + { + gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max); + } + TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages); + + if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) + { + GLint tmp; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp); + gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp); + } + else + { + gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max); + } + TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers); + + if (gl_info->supported[ARB_VERTEX_SHADER]) + { + GLint tmp; + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp); + gl_info->max_vertex_samplers = tmp; + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp); + gl_info->max_combined_samplers = tmp; + + /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup + * is known at shader link time. In a vertex shader + pixel shader combination this isn't + * an issue because then the sampler setup only depends on the two shaders. If a pixel + * shader is used with fixed function vertex processing we're fine too because fixed function + * vertex processing doesn't use any samplers. If fixed function fragment processing is + * used we have to make sure that all vertex sampler setups are valid together with all + * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES + * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards). + * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and + * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have + * 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 probably disable vertex texture fetch. */ + if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12 + && 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"); + 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; + } + TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers); + TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers); + } + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max); + gl_info->max_blends = gl_max; + TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends); + } + if (gl_info->supported[EXT_TEXTURE3D]) + { + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max); + gl_info->max_texture3d_size = gl_max; + TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size); + } + if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) + { + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max); + gl_info->max_anisotropy = gl_max; + TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy); + } + if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) + { + GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); + gl_info->ps_arb_constantsF = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF); + GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max)); + gl_info->ps_arb_max_temps = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps); + GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max)); + gl_info->ps_arb_max_instructions = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions); + GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max)); + gl_info->ps_arb_max_local_constants = gl_max; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->ps_arb_max_instructions); + } + if (gl_info->supported[ARB_VERTEX_PROGRAM]) + { + GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max)); + gl_info->vs_arb_constantsF = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF); + GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max)); + gl_info->vs_arb_max_temps = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps); + GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max)); + gl_info->vs_arb_max_instructions = gl_max; + TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions); + + if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT; + } + if (gl_info->supported[ARB_VERTEX_SHADER]) + { + glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max); + gl_info->vs_glsl_constantsF = gl_max / 4; + TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF); + } + if (gl_info->supported[ARB_FRAGMENT_SHADER]) + { + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max); + gl_info->ps_glsl_constantsF = gl_max / 4; + TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF); + glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max); + gl_info->max_glsl_varyings = gl_max; + TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4); + } + if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) + { + glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess); + } + else + { + gl_info->max_shininess = 128.0f; + } + 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; + } + if (gl_info->supported[NV_HALF_FLOAT]) + { + /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */ + gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE; + } + if (gl_info->supported[ARB_POINT_SPRITE]) + { + gl_info->max_point_sprite_units = gl_info->max_textures; + } + else + { + gl_info->max_point_sprite_units = 0; + } + checkGLcall("extension detection"); + + LEAVE_GL(); /* In some cases the number of texture stages can be larger than the number * of samplers. The GF4 for example can use only 2 samplers (no fragment @@ -1029,8 +1869,8 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { /* We can only use ORM_FBO when the hardware supports it. */ if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) { - WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n"); - wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER; + WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n"); + wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; } /* MRTs are currently only supported when FBOs are used. */ @@ -1038,357 +1878,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_info->max_buffers = 1; } - /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same - * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and - * in case of the latest videocards in the number of pixel/vertex pipelines. - * - * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for - * rendering. Various games use this information to get a rough estimation of the features of the card - * and some might use it for enabling 3d effects only on certain types of videocards. In some cases - * games might even use it to work around bugs which happen on certain videocards/driver combinations. - * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and - * not the PCI id. - * - * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse - * the renderer string and translate this to the right PCI id. This is a lot of work because there are more - * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might - * be 'small' but there are quite a number of exceptions which would make this a pain to maintain. - * Another way would be to query the PCI id from the operating system (assuming this is the videocard which - * is used for rendering which is not always the case). This would work but it is not very portable. Second - * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used - * is limited. - * - * As said most games only use the PCI id to get an indication of the capabilities of the card. - * It doesn't really matter if the given id is the correct one if we return the id of a card with - * similar 3d features. - * - * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of - * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia) - * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that - * won't pass we return a default card. This way is better than maintaining a full card database as even - * without a full database we can return a card with similar features. Second the size of the database - * can be made quite small because when you know what type of 3d functionality a card has, you know to which - * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string - * to distinguishes between different models from that family. - * - * The code also selects a default amount of video memory which we will use for an estimation of the amount - * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system - * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much - * system memory can be addressed by the system but we can make a reasonable estimation about the amount of - * 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 amount of video memory can be overruled using a registry setting. - */ - switch (gl_info->gl_vendor) { - case VENDOR_NVIDIA: - /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more - * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx. - */ - if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) { - /* Geforce 200 - highend */ - if(strstr(gl_info->gl_renderer, "GTX 280") || - strstr(gl_info->gl_renderer, "GTX 285") || - strstr(gl_info->gl_renderer, "GTX 295")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280; - vidmem = 1024; - } - /* Geforce 200 - midend high */ - if(strstr(gl_info->gl_renderer, "GTX 275")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275; - vidmem = 896; - } - /* Geforce 200 - midend */ - if(strstr(gl_info->gl_renderer, "GTX 260")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260; - vidmem = 1024; - } - /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */ - else if(strstr(gl_info->gl_renderer, "9800") || - strstr(gl_info->gl_renderer, "GTS 150") || - strstr(gl_info->gl_renderer, "GTS 250")) - { - 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 */ - } - /* Geforce9 - midend low / Geforce 200 - low*/ - else if(strstr(gl_info->gl_renderer, "9500") || - strstr(gl_info->gl_renderer, "GT 120") || - strstr(gl_info->gl_renderer, "GT 130")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT; - vidmem = 256; /* The 9500GT has 256-1024MB */ - } - /* Geforce9 - lowend */ - else if(strstr(gl_info->gl_renderer, "9400")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT; - vidmem = 256; /* The 9400GT has 256-1024MB */ - } - /* Geforce9 - lowend low */ - else if(strstr(gl_info->gl_renderer, "9100") || - strstr(gl_info->gl_renderer, "9200") || - strstr(gl_info->gl_renderer, "9300") || - strstr(gl_info->gl_renderer, "G 100")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200; - vidmem = 256; /* The 9100-9300 cards have 256MB */ - } - /* Geforce8 - highend */ - 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")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT; - vidmem = 256; - } - /* Geforce8 - lowend */ - else if(strstr(gl_info->gl_renderer, "8300") || - strstr(gl_info->gl_renderer, "8400") || - strstr(gl_info->gl_renderer, "8500")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS; - vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */ - } - /* Geforce7 - highend */ - else if(strstr(gl_info->gl_renderer, "7800") || - strstr(gl_info->gl_renderer, "7900") || - strstr(gl_info->gl_renderer, "7950") || - strstr(gl_info->gl_renderer, "Quadro FX 4") || - strstr(gl_info->gl_renderer, "Quadro FX 5")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT; - vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */ - } - /* 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 */ - } - /* Geforce6 - midend */ - else if(strstr(gl_info->gl_renderer, "6600") || - strstr(gl_info->gl_renderer, "6610") || - strstr(gl_info->gl_renderer, "6700")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT; - vidmem = 128; /* A 6600GT has 128-256MB */ - } - /* Geforce6/7 lowend */ - else { - gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */ - vidmem = 64; /* */ - } - } else if(WINE_D3D9_CAPABLE(gl_info)) { - /* GeforceFX - highend */ - if (strstr(gl_info->gl_renderer, "5800") || - strstr(gl_info->gl_renderer, "5900") || - strstr(gl_info->gl_renderer, "5950") || - strstr(gl_info->gl_renderer, "Quadro FX")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800; - vidmem = 256; /* 5800-5900 cards use 256MB */ - } - /* GeforceFX - midend */ - else if(strstr(gl_info->gl_renderer, "5600") || - strstr(gl_info->gl_renderer, "5650") || - strstr(gl_info->gl_renderer, "5700") || - strstr(gl_info->gl_renderer, "5750")) - { - gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600; - vidmem = 128; /* A 5600 uses 128-256MB */ - } - /* GeforceFX - lowend */ - else { - gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */ - vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */ - } - } else if(WINE_D3D8_CAPABLE(gl_info)) { - if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */ - vidmem = 64; /* Geforce4 Ti cards have 64-128MB */ - } - else { - gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */ - vidmem = 64; /* Geforce3 cards have 64-128MB */ - } - } else if(WINE_D3D7_CAPABLE(gl_info)) { - if (strstr(gl_info->gl_renderer, "GeForce4 MX")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */ - vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */ - } - else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */ - vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */ - } - else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) { - gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */ - vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */ - } - else { - gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */ - vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */ - } - } else { - if (strstr(gl_info->gl_renderer, "TNT2")) { - gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */ - vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */ - } - else { - gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */ - vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */ - } - } - break; - case VENDOR_ATI: - if(WINE_D3D9_CAPABLE(gl_info)) { - /* 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/HD3800 uses 256-1024MB */ - } - /* 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/HD3600 uses 256-512MB */ - } - /* 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 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") || - strstr(gl_info->gl_renderer, "X1800") || - strstr(gl_info->gl_renderer, "X1900") || - strstr(gl_info->gl_renderer, "X1950")) - { - gl_info->gl_card = CARD_ATI_RADEON_X1600; - vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */ - } - /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */ - else if(strstr(gl_info->gl_renderer, "X700") || - strstr(gl_info->gl_renderer, "X800") || - strstr(gl_info->gl_renderer, "X850") || - strstr(gl_info->gl_renderer, "X1300") || - strstr(gl_info->gl_renderer, "X1400") || - strstr(gl_info->gl_renderer, "X1450") || - strstr(gl_info->gl_renderer, "X1550")) - { - gl_info->gl_card = CARD_ATI_RADEON_X700; - vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */ - } - /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */ - else if(strstr(gl_info->gl_renderer, "Radeon Xpress")) - { - gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M; - vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */ - } - /* Radeon R3xx */ - else { - gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */ - vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */ - } - } else if(WINE_D3D8_CAPABLE(gl_info)) { - gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */ - vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */ - } else if(WINE_D3D7_CAPABLE(gl_info)) { - gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */ - vidmem = 32; /* There are models with up to 64MB */ - } else { - gl_info->gl_card = CARD_ATI_RAGE_128PRO; - vidmem = 16; /* There are 16-32MB models */ - } - break; - case VENDOR_INTEL: - if (strstr(gl_info->gl_renderer, "GMA 950") || - strstr(gl_info->gl_renderer, "945GM")) { - /* 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; - } else if (strstr(gl_info->gl_renderer, "865G")) { - gl_info->gl_card = CARD_INTEL_I865G; - } else if (strstr(gl_info->gl_renderer, "855G")) { - gl_info->gl_card = CARD_INTEL_I855G; - } else if (strstr(gl_info->gl_renderer, "830G")) { - gl_info->gl_card = CARD_INTEL_I830G; - } else { - gl_info->gl_card = CARD_INTEL_I915G; - } - break; - case VENDOR_MESA: - case VENDOR_WINE: - default: - /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice - * for Nvidia was because the hardware and drivers they make are of good quality. This makes - * them a good generic choice. - */ - gl_info->gl_vendor = VENDOR_NVIDIA; - if(WINE_D3D9_CAPABLE(gl_info)) - gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600; - else if(WINE_D3D8_CAPABLE(gl_info)) - gl_info->gl_card = CARD_NVIDIA_GEFORCE3; - else if(WINE_D3D7_CAPABLE(gl_info)) - gl_info->gl_card = CARD_NVIDIA_GEFORCE; - else if(WINE_D3D6_CAPABLE(gl_info)) - gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; - else - gl_info->gl_card = CARD_NVIDIA_RIVA_128; - } + gl_info->gl_card = wined3d_guess_card(gl_info, gl_renderer, &gl_info->gl_vendor, &vidmem); 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; */ @@ -1413,31 +1903,6 @@ static 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; - 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; - - - minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR; - minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR; - minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR; - minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST; - minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST; - minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR; - minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR; - minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST; - minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR; - minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE] - = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR; - minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT] - = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR; - minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR] - = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR; - -/* TODO: config lookups */ - /* Make sure there's an active HDC else the WGL extensions will fail */ hdc = pwglGetCurrentDC(); if (hdc) { @@ -1452,7 +1917,6 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { while (*WGL_Extensions != 0x00) { const char *Start; char ThisExtn[256]; - size_t len; while (isspace(*WGL_Extensions)) WGL_Extensions++; Start = WGL_Extensions; @@ -1466,7 +1930,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { memcpy(ThisExtn, Start, len); ThisExtn[len] = '\0'; - TRACE_(d3d_caps)("- %s\n", ThisExtn); + TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn)); if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) { gl_info->supported[WGL_ARB_PBUFFER] = TRUE; @@ -1483,9 +1947,12 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } } } - LEAVE_GL(); - return return_value; + fixup_extensions(gl_info, gl_renderer); + add_gl_compat_wrappers(gl_info); + + HeapFree(GetProcessHeap(), 0, gl_renderer); + return TRUE; } /********************************************************** @@ -1532,40 +1999,39 @@ static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Ad /* TODO: Store modes per adapter and read it from the adapter structure */ if (Adapter == 0) { /* Display */ - int i = 0; - int j = 0; + unsigned int i = 0; + unsigned int j = 0; + DEVMODEW mode; - if (!DEBUG_SINGLE_MODE) { - DEVMODEW DevModeW; + memset(&mode, 0, sizeof(mode)); + mode.dmSize = sizeof(mode); - ZeroMemory(&DevModeW, sizeof(DevModeW)); - DevModeW.dmSize = sizeof(DevModeW); - while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) { - j++; - switch (Format) - { - case WINED3DFMT_UNKNOWN: - /* This is for D3D8, do not enumerate P8 here */ - if (DevModeW.dmBitsPerPel == 32 || - DevModeW.dmBitsPerPel == 16) i++; - break; - case WINED3DFMT_X8R8G8B8: - if (DevModeW.dmBitsPerPel == 32) i++; - break; - case WINED3DFMT_R5G6B5: - if (DevModeW.dmBitsPerPel == 16) i++; - break; - case WINED3DFMT_P8: - if (DevModeW.dmBitsPerPel == 8) i++; - break; - default: - /* Skip other modes as they do not match the requested format */ - break; - } + while (EnumDisplaySettingsExW(NULL, j, &mode, 0)) + { + ++j; + switch (Format) + { + case WINED3DFMT_UNKNOWN: + /* This is for D3D8, do not enumerate P8 here */ + if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i; + break; + + case WINED3DFMT_X8R8G8B8: + if (mode.dmBitsPerPel == 32) ++i; + break; + + case WINED3DFMT_R5G6B5: + if (mode.dmBitsPerPel == 16) ++i; + break; + + case WINED3DFMT_P8: + if (mode.dmBitsPerPel == 8) ++i; + break; + + default: + /* Skip other modes as they do not match the requested format */ + break; } - } else { - i = 1; - j = 1; } TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j); @@ -1589,7 +2055,8 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte } /* TODO: Store modes per adapter and read it from the adapter structure */ - if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */ + if (Adapter == 0) + { DEVMODEW DevModeW; int ModeIdx = 0; UINT i = 0; @@ -1635,7 +2102,7 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) { pMode->Width = DevModeW.dmPelsWidth; pMode->Height = DevModeW.dmPelsHeight; - pMode->RefreshRate = WINED3DADAPTER_DEFAULT; + pMode->RefreshRate = DEFAULT_REFRESH_RATE; if (DevModeW.dmFields & DM_DISPLAYFREQUENCY) pMode->RefreshRate = DevModeW.dmDisplayFrequency; @@ -1653,14 +2120,9 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), DevModeW.dmBitsPerPel); - } else if (DEBUG_SINGLE_MODE) { - /* Return one setting of the format requested */ - if (Mode > 0) return WINED3DERR_INVALIDCALL; - pMode->Width = 800; - pMode->Height = 600; - pMode->RefreshRate = 60; - pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format; - } else { + } + else + { FIXME_(d3d_caps)("Adapter not primary display\n"); } @@ -1687,7 +2149,7 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT A pMode->Width = DevModeW.dmPelsWidth; pMode->Height = DevModeW.dmPelsHeight; bpp = DevModeW.dmBitsPerPel; - pMode->RefreshRate = WINED3DADAPTER_DEFAULT; + pMode->RefreshRate = DEFAULT_REFRESH_RATE; if (DevModeW.dmFields&DM_DISPLAYFREQUENCY) { pMode->RefreshRate = DevModeW.dmDisplayFrequency; @@ -1708,6 +2170,7 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT A static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags, WINED3DADAPTER_IDENTIFIER* pIdentifier) { IWineD3DImpl *This = (IWineD3DImpl *)iface; + size_t len; TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier); @@ -1717,44 +2180,70 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad /* Return the information requested */ TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n"); - strcpy(pIdentifier->Driver, This->adapters[Adapter].driver); - if(This->adapters[Adapter].gl_info.driver_description) - strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description); - else /* Copy default description "Direct3D HAL" */ - strcpy(pIdentifier->Description, This->adapters[Adapter].description); - /* Note dx8 doesn't supply a DeviceName */ - if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */ - pIdentifier->DriverVersion->u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart; - pIdentifier->DriverVersion->u.LowPart = This->adapters[Adapter].gl_info.driver_version; - *(pIdentifier->VendorId) = This->adapters[Adapter].gl_info.gl_vendor; - *(pIdentifier->DeviceId) = This->adapters[Adapter].gl_info.gl_card; - *(pIdentifier->SubSysId) = 0; - *(pIdentifier->Revision) = 0; - *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID; + if (pIdentifier->driver_size) + { + len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1); + memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len); + pIdentifier->driver[len] = '\0'; + } + + if (pIdentifier->description_size) + { + const char *description; + + if (This->adapters[Adapter].gl_info.driver_description) + description = This->adapters[Adapter].gl_info.driver_description; + else + description = This->adapters[Adapter].description; + + len = min(strlen(description), pIdentifier->description_size - 1); + memcpy(pIdentifier->description, description, len); + pIdentifier->description[len] = '\0'; + } + + /* Note that d3d8 doesn't supply a device name. */ + if (pIdentifier->device_name_size) + { + static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */ + + len = strlen(device_name); + if (len >= pIdentifier->device_name_size) + { + ERR("Device name size too small.\n"); + return WINED3DERR_INVALIDCALL; + } + + memcpy(pIdentifier->device_name, device_name, len); + pIdentifier->device_name[len] = '\0'; + } + + pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart; + pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version; + pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor; + pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card; + pIdentifier->subsystem_id = 0; + pIdentifier->revision = 0; + memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier)); if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE) { TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id); - *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id; + pIdentifier->device_id = wined3d_settings.pci_device_id; } if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE) { TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id); - *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id; + pIdentifier->vendor_id = wined3d_settings.pci_vendor_id; } - if (Flags & WINED3DENUM_NO_WHQL_LEVEL) { - *(pIdentifier->WHQLLevel) = 0; - } else { - *(pIdentifier->WHQLLevel) = 1; - } + pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1; return WINED3D_OK; } -static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info, +static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info, const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc) { short redSize, greenSize, blueSize, alphaSize, colorBits; @@ -1803,7 +2292,7 @@ static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_I return FALSE; } -static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info, +static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info, const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc) { short depthSize, stencilSize; @@ -1879,10 +2368,9 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT return WINED3DERR_NOTAVAILABLE; } -static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, - WINED3DFORMAT SurfaceFormat, - BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { - +static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, + WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels) +{ IWineD3DImpl *This = (IWineD3DImpl *)iface; const struct GlPixelFormatDesc *glDesc; const struct WineD3DAdapter *adapter; @@ -1902,7 +2390,10 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U /* TODO: handle Windowed, add more quality levels */ - if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK; + if (WINED3DMULTISAMPLE_NONE == MultiSampleType) { + if(pQualityLevels) *pQualityLevels = 1; + 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 @@ -2092,7 +2583,7 @@ static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter, int it=0; /* Only allow depth/stencil formats */ - if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE; + if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE; /* Walk through all WGL pixel formats to find a match */ for (it = 0; it < adapter->nCfgs; ++it) @@ -2179,7 +2670,7 @@ static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter, static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc) { - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; /* Check for supported sRGB formats (Texture loading and framebuffer) */ if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) { @@ -2259,7 +2750,7 @@ static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const stru static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc) { - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; const shader_backend_t *shader_backend; const struct fragment_pipeline *fp; @@ -2539,7 +3030,7 @@ static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc) { - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; if (!GL_LIMITS(vertex_samplers)) { TRACE_(d3d_caps)("[FAILED]\n"); @@ -2563,12 +3054,13 @@ static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const s return FALSE; } -static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, +static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, - WINED3DSURFTYPE SurfaceType) { + WINED3DSURFTYPE SurfaceType) +{ IWineD3DImpl *This = (IWineD3DImpl *)iface; struct WineD3DAdapter *adapter = &This->adapters[Adapter]; - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info); const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info); DWORD UsageCaps = 0; @@ -3047,18 +3539,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_NOTAVAILABLE; } - /* 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 - * support this format uncovers a bug in Battlefield 1942 (fonts are missing) - * So do the same as Windows drivers and pretend not to support it on dx8 and 9 - * Enable it on dx7. It will need additional checking on dx10 when we support it. - */ - if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other * usage flags match. */ @@ -3105,7 +3585,7 @@ static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adap static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType) { - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; int vs_selected_mode; int ps_selected_mode; @@ -3125,7 +3605,7 @@ static const struct fragment_pipeline *select_fragment_implementation(struct Win static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType) { - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; int vs_selected_mode; int ps_selected_mode; @@ -3144,7 +3624,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, IWineD3DImpl *This = (IWineD3DImpl *)iface; struct WineD3DAdapter *adapter = &This->adapters[Adapter]; - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; int vs_selected_mode; int ps_selected_mode; struct shader_caps shader_caps; @@ -3446,14 +3926,14 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, pCaps->MaxTextureRepeat = 32768; pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size); - pCaps->MaxVertexW = 1.0; + pCaps->MaxVertexW = 1.0f; - pCaps->GuardBandLeft = 0; - pCaps->GuardBandTop = 0; - pCaps->GuardBandRight = 0; - pCaps->GuardBandBottom = 0; + pCaps->GuardBandLeft = 0.0f; + pCaps->GuardBandTop = 0.0f; + pCaps->GuardBandRight = 0.0f; + pCaps->GuardBandBottom = 0.0f; - pCaps->ExtentsAdjust = 0; + pCaps->ExtentsAdjust = 0.0f; pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT | WINED3DSTENCILCAPS_INCRSAT | @@ -3465,9 +3945,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR | WINED3DSTENCILCAPS_INCR; } - if ( This->dxVersion > 8 && - ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || - GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) { + if (GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || GL_SUPPORT(ATI_SEPARATE_STENCIL)) { pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED; } @@ -3483,14 +3961,13 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, pCaps->MaxPointSize = GL_LIMITS(pointsize); + /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */ 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; @@ -3539,7 +4016,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, 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; + pCaps->PixelShader1xMaxValue = 0.0f; } else { pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion; pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue; @@ -3762,7 +4239,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, } else { object->surface_alignment = D3D8_PITCH_ALIGNMENT; } - object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */ + object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */ /* Set the state up as invalid until the device is fully created */ object->state = WINED3DERR_DRIVERINTERNALERROR; @@ -3788,6 +4265,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps); object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst; object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst; + object->vs_clipping = shader_caps.VSClipping; memset(&ffp_caps, 0, sizeof(ffp_caps)); frag_pipeline = select_fragment_implementation(adapter, DeviceType); @@ -3853,366 +4331,6 @@ ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) { return IUnknown_Release(volumeParent); } -static BOOL match_apple(const WineD3D_GL_Info *gl_info) -{ - /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from - * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to - * detect the Apple OpenGL implementation to apply some extension fixups afterwards. - * - * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks - * 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 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] && - gl_info->supported[APPLE_CLIENT_STORAGE] && - gl_info->supported[APPLE_FLUSH_RENDER] && - gl_info->supported[APPLE_YCBCR_422]) { - TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n"); - TRACE_(d3d_caps)("Activating MacOS fixups\n"); - return TRUE; - } else { - TRACE_(d3d_caps)("Apple extensions are not supported\n"); - TRACE_(d3d_caps)("Not activating MacOS fixups\n"); - return FALSE; - } -} - -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); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - 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"); - } -} - -/* 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 */ - const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */ - 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 (180.x) - * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown - * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89 - * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86 - * - * All version numbers used below are from the Linux nvidia drivers. - */ - {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 }, - {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 4, 3 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 4, 3 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 4, 3 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8044 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8044 }, - - /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */ - {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 }, - - /* TODO: Add information about legacy ATI hardware, Intel and other cards */ -}; - -static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info) { - if(gl_info->gl_vendor != VENDOR_ATI) return FALSE; - if(gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE; - if(gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE; - if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE; - return FALSE; -} - -static BOOL match_geforce5(const WineD3D_GL_Info *gl_info) { - if(gl_info->gl_vendor == VENDOR_NVIDIA) { - if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) { - return TRUE; - } - } - return FALSE; -} - -static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info) { - return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info); -} - -static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) { - if(!match_apple(gl_info)) return FALSE; - if(gl_info->gl_vendor != VENDOR_ATI) return FALSE; - if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE; - return TRUE; -} - -static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) { - if(gl_info->gl_vendor != VENDOR_ATI) return FALSE; - if(match_apple(gl_info)) return FALSE; - if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */ - return TRUE; -} - -static void quirk_arb_constants(WineD3D_GL_Info *gl_info) { - TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF); - gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF; - TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL\n", gl_info->ps_arb_constantsF); - gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF; -} - -static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) { - quirk_arb_constants(gl_info); - /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms. - * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should - * allow 48 different offsets or other helper immediate values - */ - TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use\n"); - gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12); -} - -/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB - * on more than one texture unit. This means that the d3d9 visual point size test will cause a - * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This - * quirk only enables point sprites on the first texture unit. This keeps point sprites working in - * most games, but avoids the crash - * - * A more sophisticated way would be to find all units that need texture coordinates and enable - * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow - * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though) - * - * Note that disabling the extension entirely does not gain predictability because there is no point - * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. - */ -static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) { - if(gl_info->supported[ARB_POINT_SPRITE]) { - TRACE("Limiting point sprites to one texture unit\n"); - gl_info->max_point_sprite_units = 1; - } -} - -static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) { - quirk_arb_constants(gl_info); - - /* 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. - */ - 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; - - /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although - * it is generally more efficient. Reserve just 8 constants - */ - TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use\n"); - gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8); -} - -static void quirk_no_np2(WineD3D_GL_Info *gl_info) { - /* 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. - */ - 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; -} - -static void quirk_texcoord_w(WineD3D_GL_Info *gl_info) { - /* 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. - */ - TRACE("Enabling vertex texture coord fixes in vertex shaders\n"); - gl_info->set_texcoord_w = TRUE; -} - -struct driver_quirk quirk_table[] = { - { - match_ati_r300_to_500, - quirk_ati_dx9, - "ATI GLSL constant and normalized texrect quirk" - }, - /* 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. - * - * ARB vp gives the correct amount of uniforms, so use it instead of GLSL - */ - { - match_apple, - quirk_apple_glsl_constants, - "Apple GLSL uniform override" - }, - { - match_geforce5, - quirk_no_np2, - "Geforce 5 NP2 disable" - }, - { - match_apple_intel, - quirk_texcoord_w, - "Init texcoord .w for Apple Intel GPU driver" - }, - { - match_apple_nonr500ati, - quirk_texcoord_w, - "Init texcoord .w for Apple ATI >= r600 GPU driver" - }, - { - match_fglrx, - quirk_one_point_sprite, - "Fglrx point sprite crash workaround" - } -}; - -static void fixup_extensions(WineD3D_GL_Info *gl_info) { - unsigned int i; - - for(i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); i++) { - if(!quirk_table[i].match(gl_info)) continue; - TRACE_(d3d_caps)("Applying driver quirk \"%s\"\n", quirk_table[i].description); - quirk_table[i].apply(gl_info); - } - - /* 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); - strcpy(gl_info->driver_description, driver_version_table[i].description); - break; - } - } -} - static void WINE_GLAPI invalid_func(const void *data) { ERR("Invalid vertex attribute function called\n"); @@ -4243,13 +4361,16 @@ static void WINE_GLAPI position_float4(const void *data) { const GLfloat *pos = data; - if (pos[3] < eps && pos[3] > -eps) - glVertex3fv(pos); - else { - float w = 1.0 / pos[3]; + if (pos[3] != 0.0f && pos[3] != 1.0f) + { + float w = 1.0f / pos[3]; glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w); } + else + { + glVertex3fv(pos); + } } static void WINE_GLAPI diffuse_d3dcolor(const void *data) @@ -4277,7 +4398,7 @@ static void WINE_GLAPI warn_no_specular_func(const void *data) WARN("GL_EXT_secondary_color not supported\n"); } -static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info) +static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info) { position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func; position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func; @@ -4435,11 +4556,11 @@ BOOL InitAdapters(IWineD3DImpl *This) * otherwise because we have to use winex11.drv's override */ #ifdef USE_WIN32_OPENGL - glFinish = (void*)GetProcAddress(mod_gl, "glFinish"); - glFlush = (void*)GetProcAddress(mod_gl, "glFlush"); + wglFinish = (void*)GetProcAddress(mod_gl, "glFinish"); + wglFlush = (void*)GetProcAddress(mod_gl, "glFlush"); #else - glFinish = (void*)pwglGetProcAddress("wglFinish"); - glFlush = (void*)pwglGetProcAddress("wglFlush"); + wglFinish = (void*)pwglGetProcAddress("wglFinish"); + wglFlush = (void*)pwglGetProcAddress("wglFlush"); #endif glEnableWINE = glEnable; @@ -4448,7 +4569,8 @@ BOOL InitAdapters(IWineD3DImpl *This) /* For now only one default adapter */ { struct WineD3DAdapter *adapter = &This->adapters[0]; - const WineD3D_GL_Info *gl_info = &adapter->gl_info; + const struct wined3d_gl_info *gl_info = &adapter->gl_info; + struct wined3d_fake_gl_ctx fake_gl_ctx = {0}; int iPixelFormat; int res; int i; @@ -4461,31 +4583,26 @@ BOOL InitAdapters(IWineD3DImpl *This) adapter->monitorPoint.x = -1; adapter->monitorPoint.y = -1; - if (!WineD3D_CreateFakeGLContext()) { + if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx)) + { ERR("Failed to get a gl context for default adapter\n"); - WineD3D_ReleaseFakeGLContext(); goto nogl_adapter; } ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info); if(!ret) { ERR("Failed to initialize gl caps for default adapter\n"); - WineD3D_ReleaseFakeGLContext(); + WineD3D_ReleaseFakeGLContext(&fake_gl_ctx); goto nogl_adapter; } ret = initPixelFormats(&adapter->gl_info); if(!ret) { ERR("Failed to init gl formats\n"); - WineD3D_ReleaseFakeGLContext(); + WineD3D_ReleaseFakeGLContext(&fake_gl_ctx); goto nogl_adapter; } - hdc = pwglGetCurrentDC(); - if(!hdc) { - ERR("Failed to get gl HDC\n"); - WineD3D_ReleaseFakeGLContext(); - goto nogl_adapter; - } + hdc = fake_gl_ctx.dc; adapter->driver = "Display"; adapter->description = "Direct3D HAL"; @@ -4622,7 +4739,7 @@ BOOL InitAdapters(IWineD3DImpl *This) { ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n"); - WineD3D_ReleaseFakeGLContext(); + WineD3D_ReleaseFakeGLContext(&fake_gl_ctx); HeapFree(GetProcessHeap(), 0, adapter->cfgs); goto nogl_adapter; } @@ -4647,10 +4764,7 @@ BOOL InitAdapters(IWineD3DImpl *This) } } - fixup_extensions(&adapter->gl_info); - add_gl_compat_wrappers(&adapter->gl_info); - - WineD3D_ReleaseFakeGLContext(); + WineD3D_ReleaseFakeGLContext(&fake_gl_ctx); select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode); select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info); diff --git a/reactos/dll/directx/wine/wined3d/drawprim.c b/reactos/dll/directx/wine/wined3d/drawprim.c index 68821b44db0..5a2c7e7aac4 100644 --- a/reactos/dll/directx/wine/wined3d/drawprim.c +++ b/reactos/dll/directx/wine/wined3d/drawprim.c @@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); #include #include +/* GL locking is done by the caller */ static void drawStridedFast(IWineD3DDevice *iface, GLenum primitive_type, UINT min_vertex_idx, UINT max_vertex_idx, UINT count, UINT idx_size, const void *idx_data, UINT start_idx) @@ -68,8 +69,10 @@ static void drawStridedFast(IWineD3DDevice *iface, GLenum primitive_type, * Slower GL version which extracts info about each vertex in turn */ -static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_info *si, UINT NumVertexes, - GLenum glPrimType, const void *idxData, UINT idxSize, UINT minIndex, UINT startIdx) +/* GL locking is done by the caller */ +static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context *context, + const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType, + const void *idxData, UINT idxSize, UINT minIndex, UINT startIdx) { unsigned int textureNo = 0; const WORD *pIdxBufS = NULL; @@ -84,6 +87,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i const BYTE *texCoords[WINED3DDP_MAXTEXCOORD]; const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL; const struct wined3d_stream_info_element *element; + UINT num_untracked_materials; DWORD tex_mask = 0; TRACE("Using slow vertex array code\n"); @@ -109,22 +113,38 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i VTRACE(("glBegin(%x)\n", glPrimType)); glBegin(glPrimType); - element = &si->elements[WINED3D_FFP_POSITION]; - if (element->data) position = element->data + streamOffset[element->stream_idx]; + if (si->use_map & (1 << WINED3D_FFP_POSITION)) + { + element = &si->elements[WINED3D_FFP_POSITION]; + position = element->data + streamOffset[element->stream_idx]; + } - element = &si->elements[WINED3D_FFP_NORMAL]; - if (element->data) normal = element->data + streamOffset[element->stream_idx]; - else glNormal3f(0, 0, 0); + if (si->use_map & (1 << WINED3D_FFP_NORMAL)) + { + element = &si->elements[WINED3D_FFP_NORMAL]; + normal = element->data + streamOffset[element->stream_idx]; + } + else + { + glNormal3f(0, 0, 0); + } - element = &si->elements[WINED3D_FFP_DIFFUSE]; - if (element->data) diffuse = element->data + streamOffset[element->stream_idx]; - else glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - if (This->activeContext->num_untracked_materials && element->format_desc->format != WINED3DFMT_A8R8G8B8) + if (si->use_map & (1 << WINED3D_FFP_DIFFUSE)) + { + element = &si->elements[WINED3D_FFP_DIFFUSE]; + diffuse = element->data + streamOffset[element->stream_idx]; + } + else + { + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } + num_untracked_materials = context->num_untracked_materials; + if (num_untracked_materials && element->format_desc->format != WINED3DFMT_A8R8G8B8) FIXME("Implement diffuse color tracking from %s\n", debug_d3dformat(element->format_desc->format)); - element = &si->elements[WINED3D_FFP_SPECULAR]; - if (element->data) + if (si->use_map & (1 << WINED3D_FFP_SPECULAR)) { + element = &si->elements[WINED3D_FFP_SPECULAR]; specular = element->data + streamOffset[element->stream_idx]; /* special case where the fog density is stored in the specular alpha channel */ @@ -159,7 +179,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i for (textureNo = 0; textureNo < texture_stages; ++textureNo) { int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX]; - int texture_idx = This->texUnitMap[textureNo]; + DWORD texture_idx = This->texUnitMap[textureNo]; if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) { @@ -169,7 +189,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i if (!pixelShader && !This->stateBlock->textures[textureNo]) continue; - if (texture_idx == -1) continue; + if (texture_idx == WINED3D_UNMAPPED_STAGE) continue; if (coordIdx > 7) { @@ -182,9 +202,9 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i continue; } - element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; - if (element->data) + if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))) { + element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; texCoords[coordIdx] = element->data + streamOffset[element->stream_idx]; tex_mask |= (1 << textureNo); } @@ -227,7 +247,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i { int coord_idx; const void *ptr; - int texture_idx; + DWORD texture_idx; if (!(tmp_tex_mask & 1)) continue; @@ -244,18 +264,20 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride; diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format_desc->emit_idx](ptrToCoords); - if(This->activeContext->num_untracked_materials) { + if (num_untracked_materials) + { DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0]; unsigned char i; float color[4]; - color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0; - color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0; - color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0; - color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0; + color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0f; + color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0f; + color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0f; + color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0f; - for(i = 0; i < This->activeContext->num_untracked_materials; i++) { - glMaterialfv(GL_FRONT_AND_BACK, This->activeContext->untracked_materials[i], color); + for (i = 0; i < num_untracked_materials; ++i) + { + glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], color); } } } @@ -295,6 +317,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_stream_i checkGLcall("glEnd and previous calls"); } +/* GL locking is done by the caller */ static inline void send_attribute(IWineD3DDeviceImpl *This, WINED3DFORMAT format, const UINT index, const void *ptr) { switch(format) @@ -397,6 +420,7 @@ static inline void send_attribute(IWineD3DDeviceImpl *This, WINED3DFORMAT format } } +/* GL locking is done by the caller */ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT minIndex, UINT startIdx) { @@ -442,8 +466,9 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream } } - for(i = MAX_ATTRIBS - 1; i >= 0; i--) { - if(!si->elements[i].data) continue; + for (i = MAX_ATTRIBS - 1; i >= 0; i--) + { + if (!(si->use_map & (1 << i))) continue; ptr = si->elements[i].data + si->elements[i].stride * SkipnStrides + @@ -457,6 +482,7 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream glEnd(); } +/* GL locking is done by the caller */ static inline void drawStridedInstanced(IWineD3DDevice *iface, const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT minIndex, UINT startIdx) @@ -496,6 +522,8 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, const struct wine for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i) { + if (!(si->use_map & (1 << i))) continue; + if (stateblock->streamFlags[si->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA) { instancedData[numInstancedAttribs] = i; @@ -532,7 +560,11 @@ static inline void remove_vbos(IWineD3DDeviceImpl *This, struct wined3d_stream_i for (i = 0; i < (sizeof(s->elements) / sizeof(*s->elements)); ++i) { - struct wined3d_stream_info_element *e = &s->elements[i]; + struct wined3d_stream_info_element *e; + + if (!(s->use_map & (1 << i))) continue; + + e = &s->elements[i]; if (e->buffer_object) { struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; @@ -549,30 +581,42 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DSurfaceImpl *target; + struct wined3d_context *context; unsigned int i; if (!index_count) 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]; - if (target) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); + if (This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE]) + { + /* 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]; + if (target) + { + IWineD3DSurface_LoadLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); + } } } /* Signals other modules that a drawing is in progress and the stateblock finalized */ This->isInDraw = TRUE; - ActivateContext(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); + context = ActivateContext(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); 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->render_offscreen properly. We don't currently take the + * Z-compare function into account, but we could skip loading the + * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note + * that we never copy the stencil data.*/ + DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE] + || This->stateBlock->renderState[WINED3DRS_ZENABLE]) + surface_load_ds_location(This->stencilBufferTarget, context, location); + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) + surface_modify_ds_location(This->stencilBufferTarget, location); } /* Ok, we will be updating the screen from here onwards so grab the lock */ @@ -587,7 +631,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice if (!use_vs(This->stateBlock)) { - if (!This->strided_streams.position_transformed && This->activeContext->num_untracked_materials + if (!This->strided_streams.position_transformed && context->num_untracked_materials && This->stateBlock->renderState[WINED3DRS_LIGHTING]) { static BOOL warned; @@ -599,7 +643,8 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice } emulation = TRUE; } - else if(This->activeContext->fog_coord && This->stateBlock->renderState[WINED3DRS_FOGENABLE]) { + else if (context->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 */ @@ -633,7 +678,8 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice } drawStridedSlowVs(iface, stream_info, index_count, glPrimType, idxData, idxSize, minIndex, StartIdx); } else { - drawStridedSlow(iface, stream_info, index_count, glPrimType, idxData, idxSize, minIndex, StartIdx); + drawStridedSlow(iface, context, stream_info, index_count, + glPrimType, idxData, idxSize, minIndex, StartIdx); } } else if(This->instancedDraw) { /* Instancing emulation with mixing immediate mode and arrays */ @@ -653,7 +699,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice #ifdef SHOW_FRAME_MAKEUP { static long int primCounter = 0; - /* NOTE: set primCounter to the value reported by drawprim + /* NOTE: set primCounter to the value reported by drawprim before you want to to write frame makeup to /tmp */ if (primCounter >= 0) { WINED3DLOCKED_RECT r; @@ -695,7 +741,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice static void normalize_normal(float *n) { float length = n[0] * n[0] + n[1] * n[1] + n[2] * n[2]; - if(length == 0.0) return; + if (length == 0.0f) return; length = sqrt(length); n[0] = n[0] / length; n[1] = n[1] / length; @@ -727,7 +773,7 @@ static void normalize_normal(float *n) { HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, struct WineD3DRectPatch *patch) { unsigned int i, j, num_quads, out_vertex_size, buffer_size, d3d_out_vertex_size; - float max_x = 0.0, max_y = 0.0, max_z = 0.0, neg_z = 0.0; + float max_x = 0.0f, max_y = 0.0f, max_z = 0.0f, neg_z = 0.0f; struct wined3d_stream_info stream_info; struct wined3d_stream_info_element *e; const BYTE *data; @@ -736,6 +782,11 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, GLenum feedback_type; GLfloat *feedbuffer; + /* Simply activate the context for blitting. This disables all the things we don't want and + * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the + * patch (as opposed to normal draws) will most likely need different changes anyway. */ + ActivateContext(This, NULL, CTXUSAGE_BLIT); + /* First, locate the position data. This is provided in a vertex buffer in the stateblock. * Beware of vbos */ @@ -786,19 +837,14 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, patch->has_normals = TRUE; patch->has_texcoords = FALSE; - /* Simply activate the context for blitting. This disables all the things we don't want and - * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the - * patch (as opposed to normal draws) will most likely need different changes anyway - */ - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_BLIT); ENTER_GL(); glMatrixMode(GL_PROJECTION); checkGLcall("glMatrixMode(GL_PROJECTION)"); glLoadIdentity(); checkGLcall("glLoadIndentity()"); - glScalef(1 / (max_x) , 1 / (max_y), max_z == 0 ? 1 : 1 / ( 2 * max_z)); - glTranslatef(0, 0, 0.5); + glScalef(1.0f / (max_x), 1.0f / (max_y), max_z == 0.0f ? 1.0f : 1.0f / (2.0f * max_z)); + glTranslatef(0.0f, 0.0f, 0.5f); checkGLcall("glScalef"); glViewport(-max_x, -max_y, 2 * (max_x), 2 * (max_y)); checkGLcall("glViewport"); @@ -810,11 +856,11 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FILLMODE)); if(patch->has_normals) { - static const GLfloat black[] = {0, 0, 0, 0}; - static const GLfloat red[] = {1, 0, 0, 0}; - static const GLfloat green[] = {0, 1, 0, 0}; - static const GLfloat blue[] = {0, 0, 1, 0}; - static const GLfloat white[] = {1, 1, 1, 1}; + static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat red[] = {1.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat green[] = {0.0f, 1.0f, 0.0f, 0.0f}; + static const GLfloat blue[] = {0.0f, 0.0f, 1.0f, 0.0f}; + static const GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f}; glEnable(GL_LIGHTING); checkGLcall("glEnable(GL_LIGHTING)"); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black); @@ -833,21 +879,21 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, glLightfv(GL_LIGHT0, GL_AMBIENT, black); glLightfv(GL_LIGHT0, GL_POSITION, red); glEnable(GL_LIGHT0); - checkGLcall("Setting up light 1\n"); + checkGLcall("Setting up light 1"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(1)); glLightfv(GL_LIGHT1, GL_DIFFUSE, green); glLightfv(GL_LIGHT1, GL_SPECULAR, black); glLightfv(GL_LIGHT1, GL_AMBIENT, black); glLightfv(GL_LIGHT1, GL_POSITION, green); glEnable(GL_LIGHT1); - checkGLcall("Setting up light 2\n"); + checkGLcall("Setting up light 2"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(2)); glLightfv(GL_LIGHT2, GL_DIFFUSE, blue); glLightfv(GL_LIGHT2, GL_SPECULAR, black); glLightfv(GL_LIGHT2, GL_AMBIENT, black); glLightfv(GL_LIGHT2, GL_POSITION, blue); glEnable(GL_LIGHT2); - checkGLcall("Setting up light 3\n"); + checkGLcall("Setting up light 3"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORVERTEX)); @@ -855,7 +901,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, white); - checkGLcall("Setting up materials\n"); + checkGLcall("Setting up materials"); } /* Enable the needed maps. @@ -895,18 +941,18 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, feedbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size * sizeof(float) * 8); glMap2f(GL_MAP2_VERTEX_3, - 0, 1, vtxStride / sizeof(float), info->Width, - 0, 1, info->Stride * vtxStride / sizeof(float), info->Height, + 0.0f, 1.0f, vtxStride / sizeof(float), info->Width, + 0.0f, 1.0f, info->Stride * vtxStride / sizeof(float), info->Height, (const GLfloat *)data); checkGLcall("glMap2f"); if(patch->has_texcoords) { glMap2f(GL_MAP2_TEXTURE_COORD_4, - 0, 1, vtxStride / sizeof(float), info->Width, - 0, 1, info->Stride * vtxStride / sizeof(float), info->Height, + 0.0f, 1.0f, vtxStride / sizeof(float), info->Width, + 0.0f, 1.0f, info->Stride * vtxStride / sizeof(float), info->Height, (const GLfloat *)data); checkGLcall("glMap2f"); } - glMapGrid2f(ceilf(patch->numSegs[0]), 0.0, 1.0, ceilf(patch->numSegs[1]), 0.0, 1.0); + glMapGrid2f(ceilf(patch->numSegs[0]), 0.0f, 1.0f, ceilf(patch->numSegs[1]), 0.0f, 1.0f); checkGLcall("glMapGrid2f"); glFeedbackBuffer(buffer_size * 2, feedback_type, feedbuffer); @@ -914,19 +960,17 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, glRenderMode(GL_FEEDBACK); glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1])); - checkGLcall("glEvalMesh2\n"); + checkGLcall("glEvalMesh2"); 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); return WINED3DERR_DRIVERINTERNALERROR; } else { @@ -950,7 +994,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, */ patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 2 + 2]; /* x, triangle 2 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 2 + 3]; /* y, triangle 2 */ - patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 2 + 4] - 0.5) * 4 * max_z; /* z, triangle 3 */ + patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 2 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 3 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 2 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 2 + 6]; @@ -960,7 +1004,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 1 + 2]; /* x, triangle 2 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 1 + 3]; /* y, triangle 2 */ - patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 1 + 4] - 0.5) * 4 * max_z; /* z, triangle 2 */ + patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 1 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 2 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 1 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 1 + 6]; @@ -970,7 +1014,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 0 + 2]; /* x, triangle 1 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 0 + 3]; /* y, triangle 1 */ - patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 0 + 4] - 0.5) * 4 * max_z; /* z, triangle 1 */ + patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 0 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 1 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 0 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 0 + 6]; @@ -981,18 +1025,18 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, if(patch->has_normals) { /* Now do the same with reverse light directions */ - static const GLfloat x[] = {-1, 0, 0, 0}; - static const GLfloat y[] = { 0, -1, 0, 0}; - static const GLfloat z[] = { 0, 0, -1, 0}; + static const GLfloat x[] = {-1.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat y[] = { 0.0f, -1.0f, 0.0f, 0.0f}; + static const GLfloat z[] = { 0.0f, 0.0f, -1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, x); glLightfv(GL_LIGHT1, GL_POSITION, y); glLightfv(GL_LIGHT2, GL_POSITION, z); - checkGLcall("Setting up reverse light directions\n"); + checkGLcall("Setting up reverse light directions"); glRenderMode(GL_FEEDBACK); checkGLcall("glRenderMode(GL_FEEDBACK)"); glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1])); - checkGLcall("glEvalMesh2\n"); + checkGLcall("glEvalMesh2"); i = glRenderMode(GL_RENDER); checkGLcall("glRenderMode(GL_RENDER)"); @@ -1006,29 +1050,29 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, ERR("Unexpected polygon: %f corners\n", feedbuffer[j + 1]); continue; } - if(patch->mem[i + 3] == 0.0) + if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 2 + 5]; - if(patch->mem[i + 4] == 0.0) + if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 2 + 6]; - if(patch->mem[i + 5] == 0.0) + if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 2 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; - if(patch->mem[i + 3] == 0.0) + if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 1 + 5]; - if(patch->mem[i + 4] == 0.0) + if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 1 + 6]; - if(patch->mem[i + 5] == 0.0) + if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 1 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; - if(patch->mem[i + 3] == 0.0) + if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 0 + 5]; - if(patch->mem[i + 4] == 0.0) + if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 0 + 6]; - if(patch->mem[i + 5] == 0.0) + if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 0 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; diff --git a/reactos/dll/directx/wine/wined3d/gl_compat.c b/reactos/dll/directx/wine/wined3d/gl_compat.c index 1fc48cc9204..9166041d7dc 100644 --- a/reactos/dll/directx/wine/wined3d/gl_compat.c +++ b/reactos/dll/directx/wine/wined3d/gl_compat.c @@ -133,7 +133,7 @@ static void WINE_GLAPI wine_glGetIntegerv(GLenum pname, GLint* params) { static void (WINE_GLAPI *old_multitex_glGetFloatv) (GLenum pname, GLfloat* params) = NULL; static void WINE_GLAPI wine_glGetFloatv(GLenum pname, GLfloat* params) { - if(pname == GL_ACTIVE_TEXTURE) *params = 0.0; + if (pname == GL_ACTIVE_TEXTURE) *params = 0.0f; else old_multitex_glGetFloatv(pname, params); } @@ -147,7 +147,7 @@ static void WINE_GLAPI wine_glGetDoublev(GLenum pname, GLdouble* params) { static void (WINE_GLAPI *old_fogcoord_glEnable) (GLenum cap) = NULL; static void WINE_GLAPI wine_glEnable(GLenum cap) { if(cap == GL_FOG) { - WineD3DContext *ctx = getActiveContext(); + struct wined3d_context *ctx = context_get_current(); ctx->fog_enabled = 1; if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return; } @@ -157,7 +157,7 @@ static void WINE_GLAPI wine_glEnable(GLenum cap) { static void (WINE_GLAPI *old_fogcoord_glDisable) (GLenum cap) = NULL; static void WINE_GLAPI wine_glDisable(GLenum cap) { if(cap == GL_FOG) { - WineD3DContext *ctx = getActiveContext(); + struct wined3d_context *ctx = context_get_current(); ctx->fog_enabled = 0; if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return; } @@ -166,8 +166,9 @@ static void WINE_GLAPI wine_glDisable(GLenum cap) { static void (WINE_GLAPI *old_fogcoord_glFogi) (GLenum pname, GLint param) = NULL; static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) { + struct wined3d_context *ctx = context_get_current(); + if(pname == GL_FOG_COORDINATE_SOURCE_EXT) { - WineD3DContext *ctx = getActiveContext(); ctx->gl_fog_source = param; if(param == GL_FRAGMENT_DEPTH_EXT) { if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG); @@ -177,9 +178,9 @@ static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) { } } else { if(pname == GL_FOG_START) { - getActiveContext()->fogstart = param; + ctx->fogstart = param; } else if(pname == GL_FOG_END) { - getActiveContext()->fogend = param; + ctx->fogend = param; } old_fogcoord_glFogi(pname, param); } @@ -187,8 +188,8 @@ static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) { static void (WINE_GLAPI *old_fogcoord_glFogiv) (GLenum pname, const GLint *param) = NULL; static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) { + struct wined3d_context *ctx = context_get_current(); if(pname == GL_FOG_COORDINATE_SOURCE_EXT) { - WineD3DContext *ctx = getActiveContext(); ctx->gl_fog_source = *param; if(*param == GL_FRAGMENT_DEPTH_EXT) { if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG); @@ -198,9 +199,9 @@ static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) { } } else { if(pname == GL_FOG_START) { - getActiveContext()->fogstart = *param; + ctx->fogstart = *param; } else if(pname == GL_FOG_END) { - getActiveContext()->fogend = *param; + ctx->fogend = *param; } old_fogcoord_glFogiv(pname, param); } @@ -208,8 +209,8 @@ static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) { static void (WINE_GLAPI *old_fogcoord_glFogf) (GLenum pname, GLfloat param) = NULL; static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) { + struct wined3d_context *ctx = context_get_current(); if(pname == GL_FOG_COORDINATE_SOURCE_EXT) { - WineD3DContext *ctx = getActiveContext(); ctx->gl_fog_source = (GLint) param; if(param == GL_FRAGMENT_DEPTH_EXT) { if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG); @@ -219,9 +220,9 @@ static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) { } } else { if(pname == GL_FOG_START) { - getActiveContext()->fogstart = param; + ctx->fogstart = param; } else if(pname == GL_FOG_END) { - getActiveContext()->fogend = param; + ctx->fogend = param; } old_fogcoord_glFogf(pname, param); } @@ -229,8 +230,8 @@ static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) { static void (WINE_GLAPI *old_fogcoord_glFogfv) (GLenum pname, const GLfloat *param) = NULL; static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) { + struct wined3d_context *ctx = context_get_current(); if(pname == GL_FOG_COORDINATE_SOURCE_EXT) { - WineD3DContext *ctx = getActiveContext(); ctx->gl_fog_source = (GLint) *param; if(*param == GL_FRAGMENT_DEPTH_EXT) { if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG); @@ -240,15 +241,14 @@ static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) { } } else { if(pname == GL_FOG_COLOR) { - WineD3DContext *ctx = getActiveContext(); ctx->fogcolor[0] = param[0]; ctx->fogcolor[1] = param[1]; ctx->fogcolor[2] = param[2]; ctx->fogcolor[3] = param[3]; } else if(pname == GL_FOG_START) { - getActiveContext()->fogstart = *param; + ctx->fogstart = *param; } else if(pname == GL_FOG_END) { - getActiveContext()->fogend = *param; + ctx->fogend = *param; } old_fogcoord_glFogfv(pname, param); } @@ -269,15 +269,15 @@ static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL; static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - WineD3DContext *ctx = getActiveContext(); + struct wined3d_context *ctx = context_get_current(); if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) { GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]}; GLfloat i; i = (ctx->fogend - ctx->fog_coord_value) / (ctx->fogend - ctx->fogstart); - c[0] = i * c[0] + (1.0 - i) * ctx->fogcolor[0]; - c[1] = i * c[1] + (1.0 - i) * ctx->fogcolor[1]; - c[2] = i * c[2] + (1.0 - i) * ctx->fogcolor[2]; + c[0] = i * c[0] + (1.0f - i) * ctx->fogcolor[0]; + c[1] = i * c[1] + (1.0f - i) * ctx->fogcolor[1]; + c[2] = i * c[2] + (1.0f - i) * ctx->fogcolor[2]; old_fogcoord_glColor4f(c[0], c[1], c[2], c[3]); old_fogcoord_glVertex4f(x, y, z, w); @@ -291,15 +291,15 @@ static void WINE_GLAPI wine_glVertex4fv(const GLfloat *pos) { } static void WINE_GLAPI wine_glVertex3f(GLfloat x, GLfloat y, GLfloat z) { - wine_glVertex4f(x, y, z, 1.0); + wine_glVertex4f(x, y, z, 1.0f); } static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) { - wine_glVertex4f(pos[0], pos[1], pos[2], 1.0); + wine_glVertex4f(pos[0], pos[1], pos[2], 1.0f); } -static void wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { - WineD3DContext *ctx = getActiveContext(); +static void WINE_GLAPI wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { + struct wined3d_context *ctx = context_get_current(); ctx->color[0] = r; ctx->color[1] = g; ctx->color[2] = b; @@ -307,43 +307,44 @@ static void wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { old_fogcoord_glColor4f(r, g, b, a); } -static void wine_glColor4fv(const GLfloat *c) { +static void WINE_GLAPI wine_glColor4fv(const GLfloat *c) { wine_glColor4f(c[0], c[1], c[2], c[3]); } -static void wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) { - wine_glColor4f(r, g, b, 1.0); +static void WINE_GLAPI wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) { + wine_glColor4f(r, g, b, 1.0f); } -static void wine_glColor3fv(const GLfloat *c) { - wine_glColor4f(c[0], c[1], c[2], 1.0); +static void WINE_GLAPI wine_glColor3fv(const GLfloat *c) { + wine_glColor4f(c[0], c[1], c[2], 1.0f); } -static void wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { - wine_glColor4f(r / 255.0, g / 255.0, b / 255.0, a / 255.0); +static void WINE_GLAPI wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { + wine_glColor4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); } /* In D3D the fog coord is a UBYTE, so there's no problem with using the single * precision function */ -static void wine_glFogCoordfEXT(GLfloat f) { - WineD3DContext *ctx = getActiveContext(); +static void WINE_GLAPI wine_glFogCoordfEXT(GLfloat f) { + struct wined3d_context *ctx = context_get_current(); ctx->fog_coord_value = f; } -static void wine_glFogCoorddEXT(GLdouble f) { +static void WINE_GLAPI wine_glFogCoorddEXT(GLdouble f) { wine_glFogCoordfEXT(f); } -static void wine_glFogCoordfvEXT(const GLfloat *f) { +static void WINE_GLAPI wine_glFogCoordfvEXT(const GLfloat *f) { wine_glFogCoordfEXT(*f); } -static void wine_glFogCoorddvEXT(const GLdouble *f) { +static void WINE_GLAPI wine_glFogCoorddvEXT(const GLdouble *f) { wine_glFogCoordfEXT(*f); } /* End GL_EXT_fog_coord emulation */ #define GLINFO_LOCATION (*gl_info) -void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info) { +void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info) +{ if(!GL_SUPPORT(ARB_MULTITEXTURE)) { TRACE("Applying GL_ARB_multitexture emulation hooks\n"); gl_info->glActiveTextureARB = wine_glActiveTextureARB; diff --git a/reactos/dll/directx/wine/wined3d/glsl_shader.c b/reactos/dll/directx/wine/wined3d/glsl_shader.c index ca503050646..b6fac0cb0ee 100644 --- a/reactos/dll/directx/wine/wined3d/glsl_shader.c +++ b/reactos/dll/directx/wine/wined3d/glsl_shader.c @@ -1,7 +1,7 @@ /* * GLSL pixel and vertex shader implementation * - * Copyright 2006 Jason Green + * Copyright 2006 Jason Green * Copyright 2006-2007 Henri Verbeet * Copyright 2007-2008 Stefan Dösinger for CodeWeavers * Copyright 2009 Henri Verbeet for CodeWeavers @@ -83,7 +83,8 @@ struct constant_heap /* GLSL shader private data */ struct shader_glsl_priv { - struct hash_table_t *glsl_program_lookup; + struct wined3d_shader_buffer shader_buffer; + struct wine_rb_tree program_lookup; struct glsl_shader_prog_link *glsl_program; struct constant_heap vconst_heap; struct constant_heap pconst_heap; @@ -94,6 +95,7 @@ struct shader_glsl_priv { /* Struct to maintain data about a linked GLSL program */ struct glsl_shader_prog_link { + struct wine_rb_entry program_lookup_entry; struct list vshader_entry; struct list pshader_entry; GLhandleARB programId; @@ -102,7 +104,7 @@ struct glsl_shader_prog_link { GLint vuniformI_locations[MAX_CONST_I]; GLint puniformI_locations[MAX_CONST_I]; GLint posFixup_location; - GLint np2Fixup_location[MAX_FRAGMENT_SAMPLERS]; + GLint np2Fixup_location; GLint bumpenvmat_location[MAX_TEXTURES]; GLint luminancescale_location[MAX_TEXTURES]; GLint luminanceoffset_location[MAX_TEXTURES]; @@ -113,6 +115,7 @@ struct glsl_shader_prog_link { struct vs_compile_args vs_args; struct ps_compile_args ps_args; UINT constant_version; + const struct ps_np2fixup_info *np2Fixup_info; }; typedef struct { @@ -122,9 +125,59 @@ typedef struct { struct vs_compile_args vs_args; } glsl_program_key_t; +struct shader_glsl_ctx_priv { + const struct vs_compile_args *cur_vs_args; + const struct ps_compile_args *cur_ps_args; + struct ps_np2fixup_info *cur_np2fixup_info; +}; + +struct glsl_ps_compiled_shader +{ + struct ps_compile_args args; + struct ps_np2fixup_info np2fixup; + GLhandleARB prgId; +}; + +struct glsl_pshader_private +{ + struct glsl_ps_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; +}; + +struct glsl_vs_compiled_shader +{ + struct vs_compile_args args; + GLhandleARB prgId; +}; + +struct glsl_vshader_private +{ + struct glsl_vs_compiled_shader *gl_shaders; + UINT num_gl_shaders, shader_array_size; +}; + +/* Extract a line from the info log. + * Note that this modifies the source string. */ +static char *get_info_log_line(char **ptr) +{ + char *p, *q; + + p = *ptr; + if (!(q = strstr(p, "\n"))) + { + if (!*p) return NULL; + *ptr += strlen(p); + return p; + } + *q = '\0'; + *ptr = q + 1; + + return p; +} /** Prints the GLSL info log which will contain error messages if they exist */ -static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) +/* GL locking is done by the caller */ +static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleARB obj) { int infologLength = 0; char *infoLog; @@ -140,10 +193,8 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) "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.\n" - "WARNING: 0:2: 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 */ }; if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return; @@ -156,6 +207,8 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) * that if there are errors. */ if (infologLength > 1) { + char *ptr, *line; + /* Fglrx doesn't terminate the string properly, but it tells us the proper length. * So use HEAP_ZERO_MEMORY to avoid uninitialized bytes */ @@ -169,10 +222,17 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) 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)); + + ptr = infoLog; + if (is_spam) + { + TRACE("Spam received from GLSL shader #%u:\n", obj); + while ((line = get_info_log_line(&ptr))) TRACE(" %s\n", line); + } + else + { + FIXME("Error received from GLSL shader #%u:\n", obj); + while ((line = get_info_log_line(&ptr))) FIXME(" %s\n", line); } HeapFree(GetProcessHeap(), 0, infoLog); } @@ -181,7 +241,9 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) /** * Loads (pixel shader) samplers */ -static void shader_glsl_load_psamplers(const WineD3D_GL_Info *gl_info, DWORD *tex_unit_map, GLhandleARB programId) +/* GL locking is done by the caller */ +static void shader_glsl_load_psamplers(const struct wined3d_gl_info *gl_info, + DWORD *tex_unit_map, GLhandleARB programId) { GLint name_loc; int i; @@ -204,7 +266,9 @@ static void shader_glsl_load_psamplers(const WineD3D_GL_Info *gl_info, DWORD *te } } -static void shader_glsl_load_vsamplers(const WineD3D_GL_Info *gl_info, DWORD *tex_unit_map, GLhandleARB programId) +/* GL locking is done by the caller */ +static void shader_glsl_load_vsamplers(const struct wined3d_gl_info *gl_info, + DWORD *tex_unit_map, GLhandleARB programId) { GLint name_loc; char sampler_name[20]; @@ -227,7 +291,8 @@ static void shader_glsl_load_vsamplers(const WineD3D_GL_Info *gl_info, DWORD *te } } -static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const float *constants, +/* GL locking is done by the caller */ +static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const float *constants, const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) { int stack_idx = 0; @@ -288,21 +353,23 @@ static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const floa checkGLcall("walk_constant_heap()"); } -static inline void apply_clamped_constant(const WineD3D_GL_Info *gl_info, GLint location, const GLfloat *data) +/* GL locking is done by the caller */ +static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info, GLint location, const GLfloat *data) { GLfloat clamped_constant[4]; if (location == -1) return; - clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0 ? 1.0 : data[0]; - clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0 ? 1.0 : data[1]; - clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0 ? 1.0 : data[2]; - clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0 ? 1.0 : data[3]; + clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0f ? 1.0f : data[0]; + clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0f ? 1.0f : data[1]; + clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0f ? 1.0f : data[2]; + clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0f ? 1.0f : data[3]; GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant)); } -static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, const float *constants, +/* GL locking is done by the caller */ +static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, const float *constants, const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) { int stack_idx = 0; @@ -362,7 +429,8 @@ static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, co } /* Loads floating point constants (aka uniforms) into the currently set GLSL program. */ -static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, const float *constants, const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, UINT version) { @@ -392,7 +460,8 @@ static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const Wine } /* Loads integer constants (aka uniforms) into the currently set GLSL program. */ -static void shader_glsl_load_constantsI(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsI(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, const GLint locations[MAX_CONST_I], const int *constants, WORD constants_set) { unsigned int i; @@ -428,16 +497,37 @@ static void shader_glsl_load_constantsI(IWineD3DBaseShaderImpl *This, const Wine } /* Loads boolean constants (aka uniforms) into the currently set GLSL program. */ -static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info, GLhandleARB programId, const BOOL *constants, WORD constants_set) { GLint tmp_loc; unsigned int i; char tmp_name[8]; - char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); - const char* prefix = is_pshader? "PB":"VB"; + const char *prefix; struct list* ptr; + switch (This->baseShader.reg_maps.shader_version.type) + { + case WINED3D_SHADER_TYPE_VERTEX: + prefix = "VB"; + break; + + case WINED3D_SHADER_TYPE_GEOMETRY: + prefix = "GB"; + break; + + case WINED3D_SHADER_TYPE_PIXEL: + prefix = "PB"; + break; + + default: + FIXME("Unknown shader type %#x.\n", + This->baseShader.reg_maps.shader_version.type); + prefix = "UB"; + break; + } + /* TODO: Benchmark and see if it would be beneficial to store the * locations of the constants to avoid looking up each time */ for (i = 0; constants_set; constants_set >>= 1, ++i) @@ -478,15 +568,15 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine } } -static void reset_program_constant_version(void *value, void *context) +static void reset_program_constant_version(struct wine_rb_entry *entry, void *context) { - struct glsl_shader_prog_link *entry = value; - entry->constant_version = 0; + WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0; } /** * Loads the texture dimensions for NP2 fixup into the currently set GLSL program. */ +/* GL locking is done by the caller (state handler) */ static void shader_glsl_load_np2fixup_constants( IWineD3DDevice* device, char usePixelShader, @@ -505,39 +595,45 @@ static void shader_glsl_load_np2fixup_constants( return; } - if (prog->ps_args.np2_fixup) { + if (prog->ps_args.np2_fixup && -1 != prog->np2Fixup_location) { + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; + const IWineD3DStateBlockImpl* stateBlock = (const IWineD3DStateBlockImpl*) deviceImpl->stateBlock; UINT i; UINT fixup = prog->ps_args.np2_fixup; - const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; - const IWineD3DStateBlockImpl* stateBlock = (const IWineD3DStateBlockImpl*) deviceImpl->stateBlock; + GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS]; for (i = 0; fixup; fixup >>= 1, ++i) { - if (-1 != prog->np2Fixup_location[i]) { - const IWineD3DBaseTextureImpl* const tex = (const IWineD3DBaseTextureImpl*) stateBlock->textures[i]; - if (!tex) { - FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n"); - continue; - } else { - const float tex_dim[2] = {tex->baseTexture.pow2Matrix[0], tex->baseTexture.pow2Matrix[5]}; - GL_EXTCALL(glUniform2fvARB(prog->np2Fixup_location[i], 1, tex_dim)); - } + const unsigned char idx = prog->np2Fixup_info->idx[i]; + const IWineD3DBaseTextureImpl* const tex = (const IWineD3DBaseTextureImpl*) stateBlock->textures[i]; + GLfloat* tex_dim = &np2fixup_constants[(idx >> 1) * 4]; + + if (!tex) { + FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n"); + continue; + } + + if (idx % 2) { + tex_dim[2] = tex->baseTexture.pow2Matrix[0]; tex_dim[3] = tex->baseTexture.pow2Matrix[5]; + } else { + tex_dim[0] = tex->baseTexture.pow2Matrix[0]; tex_dim[1] = tex->baseTexture.pow2Matrix[5]; } } + + GL_EXTCALL(glUniform4fvARB(prog->np2Fixup_location, prog->np2Fixup_info->num_consts, np2fixup_constants)); } } /** * Loads the app-supplied constants into the currently set GLSL program. */ -static void shader_glsl_load_constants( - IWineD3DDevice* device, - char usePixelShader, - char useVertexShader) { - - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; - struct shader_glsl_priv *priv = deviceImpl->shader_priv; - IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; - const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; +/* GL locking is done by the caller (state handler) */ +static void shader_glsl_load_constants(const struct wined3d_context *context, + char usePixelShader, char useVertexShader) +{ + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; + IWineD3DStateBlockImpl* stateBlock = device->stateBlock; + struct shader_glsl_priv *priv = device->shader_priv; GLhandleARB programId; struct glsl_shader_prog_link *prog = priv->glsl_program; @@ -567,7 +663,7 @@ static void shader_glsl_load_constants( stateBlock->changed.vertexShaderConstantsB & vshader->baseShader.reg_maps.boolean_constants); /* Upload the position fixup params */ - GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &deviceImpl->posFixup[0])); + GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &device->posFixup[0])); checkGLcall("glUniform4fvARB"); } @@ -590,20 +686,21 @@ static 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. */ - for(i = 0; i < ((IWineD3DPixelShaderImpl *) pshader)->numbumpenvmatconsts; i++) { - IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pshader; - int stage = ps->luminanceconst[i].texunit; + for(i = 0; i < MAX_TEXTURES; i++) { + const float *data; - const float *data = (const float *)&stateBlock->textureState[(int)ps->bumpenvmatconst[i].texunit][WINED3DTSS_BUMPENVMAT00]; + if(prog->bumpenvmat_location[i] == -1) continue; + + data = (const float *)&stateBlock->textureState[i][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(ps->baseShader.reg_maps.luminanceparams[stage]) { - const GLfloat *scale = (const GLfloat *)&stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; - const GLfloat *offset = (const GLfloat *)&stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; + if(prog->luminancescale_location[i] != -1) { + const GLfloat *scale = (const GLfloat *)&stateBlock->textureState[i][WINED3DTSS_BUMPENVLSCALE]; + const GLfloat *offset = (const GLfloat *)&stateBlock->textureState[i][WINED3DTSS_BUMPENVLOFFSET]; GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location[i], 1, scale)); checkGLcall("glUniform1fvARB"); @@ -614,13 +711,15 @@ static void shader_glsl_load_constants( if(((IWineD3DPixelShaderImpl *) pshader)->vpos_uniform) { float correction_params[4]; - if(deviceImpl->render_offscreen) { - correction_params[0] = 0.0; - correction_params[1] = 1.0; + + if (context->render_offscreen) + { + correction_params[0] = 0.0f; + correction_params[1] = 1.0f; } else { /* position is window relative, not viewport relative */ - correction_params[0] = ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height; - correction_params[1] = -1.0; + correction_params[0] = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height; + correction_params[1] = -1.0f; } GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params)); } @@ -629,7 +728,7 @@ static void shader_glsl_load_constants( if (priv->next_constant_version == UINT_MAX) { TRACE("Max constant version reached, resetting to 0.\n"); - hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL); + wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL); priv->next_constant_version = 1; } else @@ -693,24 +792,38 @@ static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT } } +static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info) +{ + unsigned int ret = GL_LIMITS(glsl_varyings) / 4; + /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */ + if(shader_major > 3) return ret; + + /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */ + if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1; + return ret; +} + /** Generate the variable & register declarations for the GLSL output target */ -static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps, - SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, - const struct ps_compile_args *ps_args) +static void shader_generate_glsl_declarations(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DBaseShader *iface, + const shader_reg_maps *reg_maps, struct shader_glsl_ctx_priv *ctx_priv) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; + const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; + const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int i, extra_constants_needed = 0; const local_constant *lconst; + DWORD map; /* There are some minor differences between pixel and vertex shaders */ char pshader = shader_is_pshader_version(reg_maps->shader_version.type); char prefix = pshader ? 'P' : 'V'; /* Prototype the subroutines */ - for (i = 0; i < This->baseShader.limits.label; i++) { - if (reg_maps->labels[i]) - shader_addline(buffer, "void subroutine%u();\n", i); + for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i); } /* Declare the constants (aka uniforms) */ @@ -737,9 +850,11 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix). * Subtract another uniform for immediate values, which have to be loaded via uniform by the driver as well. * The shader code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex shader code, so one vec4 should be enough - * (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float + * (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float). + * + * Writing gl_ClipPos requires one uniform for each clipplane as well. */ - max_constantsF = GL_LIMITS(vshader_constantsF) - 3; + max_constantsF = GL_LIMITS(vshader_constantsF) - 3 - GL_LIMITS(clipplanes); max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants); /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly, * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but @@ -784,35 +899,28 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s shader_addline(buffer, "void order_ps_input();\n"); } } else { - IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; + for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; - 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; + if (reg_maps->luminanceparams & (1 << 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(ps_args->srgb_correction) { - shader_addline(buffer, "const vec4 srgb_mul_low = vec4(%f, %f, %f, %f);\n", - srgb_mul_low, srgb_mul_low, srgb_mul_low, srgb_mul_low); - shader_addline(buffer, "const vec4 srgb_comparison = vec4(%f, %f, %f, %f);\n", - srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp); + if (ps_args->srgb_correction) + { + shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n", + srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low); + shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n", + srgb_cmp); } if(reg_maps->vpos || reg_maps->usesdsy) { if(This->baseShader.limits.constant_float + extra_constants_needed + 1 < GL_LIMITS(pshader_constantsF)) { @@ -825,14 +933,14 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s */ FIXME("Cannot find a free uniform for vpos correction params\n"); shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n", - device->render_offscreen ? 0.0 : ((IWineD3DSurfaceImpl *) device->render_targets[0])->currentDesc.Height, - device->render_offscreen ? 1.0 : -1.0); + context->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height, + context->render_offscreen ? 1.0f : -1.0f); } shader_addline(buffer, "vec4 vpos;\n"); } } - /* Declare texture samplers */ + /* Declare texture samplers */ for (i = 0; i < This->baseShader.limits.sampler; i++) { if (reg_maps->sampler_type[i]) { @@ -848,15 +956,6 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s } else { shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); } - - if (pshader && ps_args->np2_fixup & (1 << i)) - { - /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] - * while D3D has them in the (normalized) [0,1]x[0,1] range. - * samplerNP2Fixup stores texture dimensions and is updated through - * shader_glsl_load_np2fixup_constants when the sampler changes. */ - shader_addline(buffer, "uniform vec2 %csamplerNP2Fixup%u;\n", prefix, i); - } break; case WINED3DSTT_CUBE: shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i); @@ -871,17 +970,48 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s } } } - + + /* Declare uniforms for NP2 texcoord fixup: + * This is NOT done inside the loop that declares the texture samplers since the NP2 fixup code + * is currently only used for the GeforceFX series and when forcing the ARB_npot extension off. + * Modern cards just skip the code anyway, so put it inside a separate loop. */ + if (pshader && ps_args->np2_fixup) { + + struct ps_np2fixup_info* const fixup = ctx_priv->cur_np2fixup_info; + UINT cur = 0; + + /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] + * while D3D has them in the (normalized) [0,1]x[0,1] range. + * samplerNP2Fixup stores texture dimensions and is updated through + * shader_glsl_load_np2fixup_constants when the sampler changes. */ + + for (i = 0; i < This->baseShader.limits.sampler; ++i) { + if (reg_maps->sampler_type[i]) { + if (!(ps_args->np2_fixup & (1 << i))) continue; + + if (WINED3DSTT_2D != reg_maps->sampler_type[i]) { + FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n"); + continue; + } + + fixup->idx[i] = cur++; + } + } + + fixup->num_consts = (cur + 1) >> 1; + shader_addline(buffer, "uniform vec4 %csamplerNP2Fixup[%u];\n", prefix, fixup->num_consts); + } + /* Declare address variables */ - for (i = 0; i < This->baseShader.limits.address; i++) { - if (reg_maps->address[i]) - shader_addline(buffer, "ivec4 A%d;\n", i); + for (i = 0, map = reg_maps->address; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i); } /* 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%u = gl_TexCoord[%u];\n", i, i); + for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i) + { + if (map & 1) 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 @@ -891,13 +1021,13 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s { if (use_vs(device->stateBlock)) { - shader_addline(buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(reg_maps->shader_version.major, gl_info)); } 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[%u];\n", GL_LIMITS(glsl_varyings) / 4); + shader_addline(buffer, "vec4 IN[%u];\n", vec4_varyings(reg_maps->shader_version.major, gl_info)); } } @@ -907,15 +1037,18 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s } /* Declare temporary variables */ - for(i = 0; i < This->baseShader.limits.temporary; i++) { - if (reg_maps->temporary[i]) - shader_addline(buffer, "vec4 R%u;\n", i); + for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "vec4 R%u;\n", i); } /* Declare attributes */ - for (i = 0; i < This->baseShader.limits.attributes; i++) { - if (reg_maps->attributes[i]) - shader_addline(buffer, "attribute vec4 attrib%i;\n", i); + if (reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX) + { + for (i = 0, map = reg_maps->input_registers; map; map >>= 1, ++i) + { + if (map & 1) shader_addline(buffer, "attribute vec4 attrib%i;\n", i); + } } /* Declare loop registers aLx */ @@ -971,22 +1104,22 @@ static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *i /** Used for opcode modifiers - They multiply the result by the specified amount */ static const char * const shift_glsl_tab[] = { - "", /* 0 (none) */ - "2.0 * ", /* 1 (x2) */ - "4.0 * ", /* 2 (x4) */ - "8.0 * ", /* 3 (x8) */ - "16.0 * ", /* 4 (x16) */ - "32.0 * ", /* 5 (x32) */ - "", /* 6 (x64) */ - "", /* 7 (x128) */ - "", /* 8 (d256) */ - "", /* 9 (d128) */ - "", /* 10 (d64) */ - "", /* 11 (d32) */ - "0.0625 * ", /* 12 (d16) */ - "0.125 * ", /* 13 (d8) */ - "0.25 * ", /* 14 (d4) */ - "0.5 * " /* 15 (d2) */ + "", /* 0 (none) */ + "2.0 * ", /* 1 (x2) */ + "4.0 * ", /* 2 (x4) */ + "8.0 * ", /* 3 (x8) */ + "16.0 * ", /* 4 (x16) */ + "32.0 * ", /* 5 (x32) */ + "", /* 6 (x64) */ + "", /* 7 (x128) */ + "", /* 8 (d256) */ + "", /* 9 (d128) */ + "", /* 10 (d64) */ + "", /* 11 (d32) */ + "0.0625 * ", /* 12 (d16) */ + "0.125 * ", /* 13 (d8) */ + "0.25 * ", /* 14 (d4) */ + "0.5 * " /* 15 (d2) */ }; /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */ @@ -1050,7 +1183,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); *is_color = FALSE; @@ -1065,7 +1198,8 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * /* vertex shaders */ if (!pshader) { - if (((IWineD3DVertexShaderImpl *)This)->cur_args->swizzle_map & (1 << reg->idx)) *is_color = TRUE; + struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + if (priv->cur_vs_args->swizzle_map & (1 << reg->idx)) *is_color = TRUE; sprintf(register_name, "attrib%u", reg->idx); break; } @@ -1074,7 +1208,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * if (This->baseShader.reg_maps.shader_version.major >= 3) { DWORD idx = ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg->idx]; - DWORD in_count = GL_LIMITS(glsl_varyings) / 4; + unsigned int in_count = vec4_varyings(This->baseShader.reg_maps.shader_version.major, gl_info); if (reg->rel_addr) { @@ -1175,11 +1309,9 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * case WINED3DSPR_COLOROUT: if (reg->idx >= GL_LIMITS(buffers)) - WARN("Write to render target %u, only %d supported\n", reg->idx, 4); + WARN("Write to render target %u, only %d supported\n", reg->idx, GL_LIMITS(buffers)); - if (GL_SUPPORT(ARB_DRAW_BUFFERS)) sprintf(register_name, "gl_FragData[%u]", reg->idx); - /* On older cards with GLSL support like the GeforceFX there's only one buffer. */ - else sprintf(register_name, "gl_FragColor"); + sprintf(register_name, "gl_FragData[%u]", reg->idx); break; case WINED3DSPR_RASTOUT: @@ -1224,13 +1356,13 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register * switch (reg->immconst_type) { case WINED3D_IMMCONST_FLOAT: - sprintf(register_name, "%.8e", *(float *)reg->immconst_data); + sprintf(register_name, "%.8e", *(const float *)reg->immconst_data); break; case WINED3D_IMMCONST_FLOAT4: sprintf(register_name, "vec4(%.8e, %.8e, %.8e, %.8e)", - *(float *)®->immconst_data[0], *(float *)®->immconst_data[1], - *(float *)®->immconst_data[2], *(float *)®->immconst_data[3]); + *(const float *)®->immconst_data[0], *(const float *)®->immconst_data[1], + *(const float *)®->immconst_data[2], *(const float *)®->immconst_data[3]); break; default: @@ -1344,7 +1476,7 @@ static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction * } /* Append the destination part of the instruction to the buffer, return the effective write mask */ -static DWORD shader_glsl_append_dst_ext(SHADER_BUFFER *buffer, +static DWORD shader_glsl_append_dst_ext(struct wined3d_shader_buffer *buffer, const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst) { glsl_dst_param_t glsl_dst; @@ -1357,7 +1489,7 @@ static DWORD shader_glsl_append_dst_ext(SHADER_BUFFER *buffer, } /* Append the destination part of the instruction to the buffer, return the effective write mask */ -static DWORD shader_glsl_append_dst(SHADER_BUFFER *buffer, const struct wined3d_shader_instruction *ins) +static DWORD shader_glsl_append_dst(struct wined3d_shader_buffer *buffer, const struct wined3d_shader_instruction *ins) { return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]); } @@ -1599,11 +1731,11 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; - fixup = This->cur_args->color_fixup[sampler]; + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + fixup = priv->cur_ps_args->color_fixup[sampler]; sampler_base = "Psampler"; - if(This->cur_args->np2_fixup & (1 << sampler)) { + if(priv->cur_ps_args->np2_fixup & (1 << sampler)) { if(bias) { FIXME("Biased sampling from NP2 textures is unsupported\n"); } else { @@ -1627,7 +1759,11 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s shader_addline(ins->ctx->buffer, ", %s)%s);\n", bias, dst_swizzle); } else { if (np2_fixup) { - shader_addline(ins->ctx->buffer, " * PsamplerNP2Fixup%u)%s);\n", sampler, dst_swizzle); + const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; + const unsigned char idx = priv->cur_np2fixup_info->idx[sampler]; + + shader_addline(ins->ctx->buffer, " * PsamplerNP2Fixup[%u].%s)%s);\n", idx >> 1, + (idx % 2) ? "zw" : "xy", dst_swizzle); } else if(dx && dy) { shader_addline(ins->ctx->buffer, ", %s, %s)%s);\n", dx, dy, dst_swizzle); } else { @@ -1641,15 +1777,13 @@ static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_s } /***************************************************************************** - * * Begin processing individual instruction opcodes - * ****************************************************************************/ /* Generate GLSL arithmetic functions (dst = src1 + src2) */ static void shader_glsl_arith(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD write_mask; @@ -1676,7 +1810,7 @@ static void shader_glsl_arith(const struct wined3d_shader_instruction *ins) /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; DWORD write_mask; @@ -1714,7 +1848,7 @@ static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */ static void shader_glsl_dot(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD dst_write_mask, src_write_mask; @@ -1762,7 +1896,7 @@ static void shader_glsl_cross(const struct wined3d_shader_instruction *ins) * GLSL uses the value as-is. */ static void shader_glsl_pow(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; glsl_src_param_t src1_param; DWORD dst_write_mask; @@ -1786,7 +1920,7 @@ static void shader_glsl_pow(const struct wined3d_shader_instruction *ins) * GLSL uses the value as-is. */ static void shader_glsl_log(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; DWORD dst_write_mask; unsigned int dst_size; @@ -1806,7 +1940,7 @@ static void shader_glsl_log(const struct wined3d_shader_instruction *ins) /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */ static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src_param; const char *instruction; DWORD write_mask; @@ -1910,7 +2044,7 @@ static void shader_glsl_rcp(const struct wined3d_shader_instruction *ins) static void shader_glsl_rsq(const struct wined3d_shader_instruction *ins) { - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src_param; DWORD write_mask; unsigned int mask_size; @@ -2128,8 +2262,8 @@ static void shader_glsl_mad(const struct wined3d_shader_instruction *ins) src0_param.param_str, src1_param.param_str, src2_param.param_str); } -/** Handles transforming all WINED3DSIO_M?x? opcodes for - Vertex shaders to GLSL codes */ +/* Handles transforming all WINED3DSIO_M?x? opcodes for + Vertex shaders to GLSL codes */ static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) { int i; @@ -2185,7 +2319,7 @@ static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) } /** - The LRP instruction performs a component-wise linear interpolation + The LRP instruction performs a component-wise linear interpolation between the second and third operands using the first operand as the blend factor. Equation: (dst = src2 + src0 * (src1 - src2)) This is equivalent to mix(src2, src1, src0); @@ -2282,7 +2416,7 @@ static void shader_glsl_dst(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_SINCOS instruction in GLSL: * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params. - * + * * dst.x = cos(src0.?) * dst.y = sin(src0.?) * dst.z = dst.z @@ -2346,22 +2480,33 @@ static void shader_glsl_loop(const struct wined3d_shader_instruction *ins) } } - if(control_values) { - if(control_values[2] > 0) { - shader_addline(ins->ctx->buffer, "for (aL%u = %d; aL%u < (%d * %d + %d); aL%u += %d) {\n", - shader->baseShader.cur_loop_depth, control_values[1], - shader->baseShader.cur_loop_depth, control_values[0], control_values[2], control_values[1], - shader->baseShader.cur_loop_depth, control_values[2]); - } else if(control_values[2] == 0) { - shader_addline(ins->ctx->buffer, "for (aL%u = %d, tmpInt%u = 0; tmpInt%u < %d; tmpInt%u++) {\n", - shader->baseShader.cur_loop_depth, control_values[1], shader->baseShader.cur_loop_depth, - shader->baseShader.cur_loop_depth, control_values[0], + if (control_values) + { + struct wined3d_shader_loop_control loop_control; + loop_control.count = control_values[0]; + loop_control.start = control_values[1]; + loop_control.step = (int)control_values[2]; + + if (loop_control.step > 0) + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.count, loop_control.step, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.step); + } + else if (loop_control.step < 0) + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.count, loop_control.step, loop_control.start, + shader->baseShader.cur_loop_depth, loop_control.step); + } + else + { + shader_addline(ins->ctx->buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++) {\n", + shader->baseShader.cur_loop_depth, loop_control.start, shader->baseShader.cur_loop_depth, + shader->baseShader.cur_loop_depth, loop_control.count, shader->baseShader.cur_loop_depth); - } else { - shader_addline(ins->ctx->buffer, "for (aL%u = %d; aL%u > (%d * %d + %d); aL%u += %d) {\n", - shader->baseShader.cur_loop_depth, control_values[1], - shader->baseShader.cur_loop_depth, control_values[0], control_values[2], control_values[1], - shader->baseShader.cur_loop_depth, control_values[2]); } } else { shader_addline(ins->ctx->buffer, @@ -2488,10 +2633,17 @@ static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins) shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n", src1_param.param_str, ins->src[0].reg.idx); } +static void shader_glsl_ret(const struct wined3d_shader_instruction *ins) +{ + /* No-op. The closing } is written when a new function is started, and at the end of the shader. This + * function only suppresses the unhandled instruction warning + */ +} + /********************************************* * Pixel Shader Specific Code begins here ********************************************/ -static void pshader_glsl_tex(const struct wined3d_shader_instruction *ins) +static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; @@ -2584,7 +2736,7 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; glsl_sample_function_t sample_function; glsl_src_param_t coord_param, dx_param, dy_param; DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD; @@ -2594,7 +2746,7 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) if(!GL_SUPPORT(ARB_SHADER_TEXTURE_LOD)) { FIXME("texldd used, but not supported by hardware. Falling back to regular tex\n"); - return pshader_glsl_tex(ins); + return shader_glsl_tex(ins); } sampler_idx = ins->src[1].reg.idx; @@ -2617,6 +2769,7 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) { IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info; glsl_sample_function_t sample_function; glsl_src_param_t coord_param, lod_param; DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD; @@ -2635,7 +2788,8 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); - if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) + if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] + && shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { /* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders. * However, they seem to work just fine in fragment shaders as well. */ @@ -2645,10 +2799,10 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) "%s", coord_param.param_str); } -static void pshader_glsl_texcoord(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins) { /* FIXME: Make this work for more than just 2D textures */ - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4)) @@ -2694,7 +2848,7 @@ static void pshader_glsl_texcoord(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL: * Take a 3-component dot product of the TexCoord[dstreg] and src, * then perform a 1D texture lookup from stage dstregnum, place into dst. */ -static void pshader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; glsl_sample_function_t sample_function; @@ -2738,7 +2892,7 @@ static void pshader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXDP3 instruction in GLSL: * Take a 3-component dot product of the TexCoord[dstreg] and src. */ -static void pshader_glsl_texdp3(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; DWORD dstreg = ins->dst[0].reg.idx; @@ -2759,7 +2913,7 @@ static void pshader_glsl_texdp3(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXDEPTH instruction in GLSL: * Calculate the depth as dst.x / dst.y */ -static void pshader_glsl_texdepth(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins) { glsl_dst_param_t dst_param; @@ -2780,7 +2934,7 @@ static void pshader_glsl_texdepth(const struct wined3d_shader_instruction *ins) * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y */ -static void pshader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins) { DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD dstreg = ins->dst[0].reg.idx; @@ -2794,11 +2948,11 @@ static void pshader_glsl_texm3x2depth(const struct wined3d_shader_instruction *i /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL * Calculate the 1st of a 2-row matrix multiplication. */ -static void pshader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins) { DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); @@ -2807,12 +2961,12 @@ static void pshader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins /** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */ -static void pshader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; glsl_src_param_t src0_param; @@ -2821,11 +2975,11 @@ static void pshader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins current_state->texcoord_w[current_state->current_row++] = reg; } -static void pshader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) { DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; glsl_src_param_t src0_param; WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg]; glsl_sample_function_t sample_function; @@ -2841,7 +2995,7 @@ static void pshader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */ -static void pshader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) { DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; glsl_src_param_t src0_param; @@ -2865,7 +3019,7 @@ static void pshader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins /** Process the WINED3DSIO_TEXM3X3 instruction in GLSL * Perform the 3rd row of a 3x3 matrix multiply */ -static void pshader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) { DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; glsl_src_param_t src0_param; @@ -2883,15 +3037,15 @@ static void pshader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) current_state->current_row = 0; } -/** Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL +/* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ -static void pshader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader; DWORD reg = ins->dst[0].reg.idx; glsl_src_param_t src0_param; glsl_src_param_t src1_param; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; WINED3DSAMPLER_TEXTURE_TYPE stype = ins->ctx->reg_maps->sampler_type[reg]; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; @@ -2914,13 +3068,13 @@ static void pshader_glsl_texm3x3spec(const struct wined3d_shader_instruction *in current_state->current_row = 0; } -/** Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL +/* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ -static void pshader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader; DWORD reg = ins->dst[0].reg.idx; - SHADER_BUFFER *buffer = ins->ctx->buffer; + struct wined3d_shader_buffer *buffer = ins->ctx->buffer; SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state; glsl_src_param_t src0_param; DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; @@ -2950,7 +3104,7 @@ static void pshader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *i * Apply a fake bump map transform. * texbem is pshader <= 1.3 only, this saves a few version checks */ -static void pshader_glsl_texbem(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; @@ -3009,7 +3163,7 @@ static void pshader_glsl_texbem(const struct wined3d_shader_instruction *ins) } } -static void pshader_glsl_bem(const struct wined3d_shader_instruction *ins) +static void shader_glsl_bem(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param, src1_param; DWORD sampler_idx = ins->dst[0].reg.idx; @@ -3024,7 +3178,7 @@ static void pshader_glsl_bem(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ -static void pshader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; @@ -3040,7 +3194,7 @@ static void pshader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXREG2GB instruction in GLSL * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */ -static void pshader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; @@ -3056,7 +3210,7 @@ static void pshader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */ -static void pshader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; DWORD sampler_idx = ins->dst[0].reg.idx; @@ -3073,7 +3227,7 @@ static void pshader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins /** Process the WINED3DSIO_TEXKILL instruction in GLSL. * If any of the first 3 components are < 0, discard this pixel */ -static void pshader_glsl_texkill(const struct wined3d_shader_instruction *ins) +static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins) { glsl_dst_param_t dst_param; @@ -3094,7 +3248,7 @@ static void pshader_glsl_texkill(const struct wined3d_shader_instruction *ins) /** Process the WINED3DSIO_DP2ADD instruction in GLSL. * dst = dot2(src0, src1) + src2 */ -static void pshader_glsl_dp2add(const struct wined3d_shader_instruction *ins) +static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins) { glsl_src_param_t src0_param; glsl_src_param_t src1_param; @@ -3118,52 +3272,52 @@ static void pshader_glsl_dp2add(const struct wined3d_shader_instruction *ins) } } -static void pshader_glsl_input_pack(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, - const struct wined3d_shader_semantic *semantics_in, const struct shader_reg_maps *reg_maps, +static void shader_glsl_input_pack(IWineD3DPixelShader *iface, struct wined3d_shader_buffer *buffer, + const struct wined3d_shader_signature_element *input_signature, const struct shader_reg_maps *reg_maps, enum vertexprocessing_mode vertexprocessing) { unsigned int i; IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; + WORD map = reg_maps->input_registers; - for (i = 0; i < MAX_REG_INPUT; ++i) + for (i = 0; map; map >>= 1, ++i) { - DWORD usage, usage_idx; + const char *semantic_name; + UINT semantic_idx; char reg_mask[6]; /* Unused */ - if (!reg_maps->packed_input[i]) continue; + if (!(map & 1)) continue; - usage = semantics_in[i].usage; - usage_idx = semantics_in[i].usage_idx; - shader_glsl_get_write_mask(&semantics_in[i].reg, reg_mask); + semantic_name = input_signature[i].semantic_name; + semantic_idx = input_signature[i].semantic_idx; + shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask); - switch (usage) + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) { - case WINED3DDECLUSAGE_TEXCOORD: - if (usage_idx < 8 && vertexprocessing == pretransformed) - shader_addline(buffer, "IN[%u]%s = gl_TexCoord[%u]%s;\n", - This->input_reg_map[i], reg_mask, usage_idx, reg_mask); - else - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - This->input_reg_map[i], reg_mask, reg_mask); - break; - - case WINED3DDECLUSAGE_COLOR: - if (usage_idx == 0) - shader_addline(buffer, "IN[%u]%s = vec4(gl_Color)%s;\n", - This->input_reg_map[i], reg_mask, reg_mask); - else if (usage_idx == 1) - shader_addline(buffer, "IN[%u]%s = vec4(gl_SecondaryColor)%s;\n", - This->input_reg_map[i], reg_mask, reg_mask); - else - shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - This->input_reg_map[i], reg_mask, reg_mask); - break; - - default: + if (semantic_idx < 8 && vertexprocessing == pretransformed) + shader_addline(buffer, "IN[%u]%s = gl_TexCoord[%u]%s;\n", + This->input_reg_map[i], reg_mask, semantic_idx, reg_mask); + else shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", This->input_reg_map[i], reg_mask, reg_mask); - break; + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx == 0) + shader_addline(buffer, "IN[%u]%s = vec4(gl_Color)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + else if (semantic_idx == 1) + shader_addline(buffer, "IN[%u]%s = vec4(gl_SecondaryColor)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + else + shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); + } + else + { + shader_addline(buffer, "IN[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + This->input_reg_map[i], reg_mask, reg_mask); } } } @@ -3173,20 +3327,23 @@ static void pshader_glsl_input_pack(IWineD3DPixelShader *iface, SHADER_BUFFER *b ********************************************/ static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) { - glsl_program_key_t *key; + glsl_program_key_t key; - key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t)); - key->vshader = entry->vshader; - key->pshader = entry->pshader; - key->vs_args = entry->vs_args; - key->ps_args = entry->ps_args; + key.vshader = entry->vshader; + key.pshader = entry->pshader; + key.vs_args = entry->vs_args; + key.ps_args = entry->ps_args; - hash_table_put(priv->glsl_program_lookup, key, entry); + if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1) + { + ERR("Failed to insert program entry.\n"); + } } static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_priv *priv, IWineD3DVertexShader *vshader, IWineD3DPixelShader *pshader, struct vs_compile_args *vs_args, struct ps_compile_args *ps_args) { + struct wine_rb_entry *entry; glsl_program_key_t key; key.vshader = vshader; @@ -3194,20 +3351,21 @@ static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_p key.vs_args = *vs_args; key.ps_args = *ps_args; - return hash_table_get(priv->glsl_program_lookup, &key); + entry = wine_rb_get(&priv->program_lookup, &key); + return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL; } -static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info, struct glsl_shader_prog_link *entry) { - glsl_program_key_t *key; + glsl_program_key_t key; - key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t)); - key->vshader = entry->vshader; - key->pshader = entry->pshader; - key->vs_args = entry->vs_args; - key->ps_args = entry->ps_args; - hash_table_remove(priv->glsl_program_lookup, key); + key.vshader = entry->vshader; + key.pshader = entry->pshader; + key.vs_args = entry->vs_args; + key.ps_args = entry->ps_args; + wine_rb_remove(&priv->program_lookup, &key); GL_EXTCALL(glDeleteObjectARB(entry->programId)); if (entry->vshader) list_remove(&entry->vshader_entry); @@ -3217,28 +3375,33 @@ static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const WineD HeapFree(GetProcessHeap(), 0, entry); } -static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, const DWORD *map, - const struct wined3d_shader_semantic *semantics_in, const struct shader_reg_maps *reg_maps_in, - const struct wined3d_shader_semantic *semantics_out, const struct shader_reg_maps *reg_maps_out) +static void handle_ps3_input(struct wined3d_shader_buffer *buffer, const struct wined3d_gl_info *gl_info, const DWORD *map, + const struct wined3d_shader_signature_element *input_signature, const struct shader_reg_maps *reg_maps_in, + const struct wined3d_shader_signature_element *output_signature, const struct shader_reg_maps *reg_maps_out) { unsigned int i, j; - DWORD usage, usage_idx, usage_out, usage_idx_out; + const char *semantic_name_in, *semantic_name_out; + UINT semantic_idx_in, semantic_idx_out; DWORD *set; DWORD in_idx; - DWORD in_count = GL_LIMITS(glsl_varyings) / 4; + unsigned int in_count = vec4_varyings(3, gl_info); char reg_mask[6], reg_mask_out[6]; char destination[50]; + WORD input_map, output_map; set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2)); - if (!semantics_out) { + if (!output_signature) + { /* 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++) { - if (!reg_maps_in->packed_input[i]) continue; + input_map = reg_maps_in->input_registers; + for (i = 0; input_map; input_map >>= 1, ++i) + { + if (!(input_map & 1)) continue; in_idx = map[i]; if (in_idx >= (in_count + 2)) { @@ -3259,56 +3422,65 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_in sprintf(destination, "IN[%u]", in_idx); } - usage = semantics_in[i].usage; - usage_idx = semantics_in[i].usage_idx; - set[map[i]] = shader_glsl_get_write_mask(&semantics_in[i].reg, reg_mask); + semantic_name_in = input_signature[i].semantic_name; + semantic_idx_in = input_signature[i].semantic_idx; + set[map[i]] = input_signature[i].mask; + shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask); - if(!semantics_out) { - switch(usage) { - case WINED3DDECLUSAGE_COLOR: - if (usage_idx == 0) - shader_addline(buffer, "%s%s = front_color%s;\n", - destination, reg_mask, reg_mask); - else if (usage_idx == 1) - shader_addline(buffer, "%s%s = front_secondary_color%s;\n", - destination, reg_mask, reg_mask); - else - 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, "%s%s = gl_TexCoord[%u]%s;\n", - destination, reg_mask, usage_idx, reg_mask); - } else { - 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, "%s%s = vec4(gl_FogFragCoord, 0.0, 0.0, 0.0)%s;\n", - destination, reg_mask, reg_mask); - break; - - default: + if (!output_signature) + { + if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx_in == 0) + shader_addline(buffer, "%s%s = front_color%s;\n", + destination, reg_mask, reg_mask); + else if (semantic_idx_in == 1) + shader_addline(buffer, "%s%s = front_secondary_color%s;\n", + destination, reg_mask, reg_mask); + else shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", - destination, reg_mask, reg_mask); + destination, reg_mask, reg_mask); + } + else if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_TEXCOORD)) + { + if (semantic_idx_in < 8) + { + shader_addline(buffer, "%s%s = gl_TexCoord[%u]%s;\n", + destination, reg_mask, semantic_idx_in, reg_mask); + } + else + { + shader_addline(buffer, "%s%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + } + else if (shader_match_semantic(semantic_name_in, WINED3DDECLUSAGE_FOG)) + { + shader_addline(buffer, "%s%s = vec4(gl_FogFragCoord, 0.0, 0.0, 0.0)%s;\n", + destination, reg_mask, reg_mask); + } + else + { + 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; - for(j = 0; j < MAX_REG_OUTPUT; j++) { - if (!reg_maps_out->packed_output[j]) continue; - usage_out = semantics_out[j].usage; - usage_idx_out = semantics_out[j].usage_idx; - shader_glsl_get_write_mask(&semantics_out[j].reg, reg_mask_out); + output_map = reg_maps_out->output_registers; + for (j = 0; output_map; output_map >>= 1, ++j) + { + if (!(output_map & 1)) continue; - if(usage == usage_out && - usage_idx == usage_idx_out) { + semantic_name_out = output_signature[j].semantic_name; + semantic_idx_out = output_signature[j].semantic_idx; + shader_glsl_write_mask_to_str(output_signature[j].mask, reg_mask_out); + + if (semantic_idx_in == semantic_idx_out + && !strcmp(semantic_name_in, semantic_name_out)) + { shader_addline(buffer, "%s%s = OUT[%u]%s;\n", - destination, reg_mask, j, reg_mask); + destination, reg_mask, j, reg_mask); found = TRUE; } } @@ -3324,7 +3496,8 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_in * input varyings are assigned above, if the optimizer works properly. */ for(i = 0; i < in_count + 2; i++) { - if(set[i] != WINED3DSP_WRITEMASK_ALL) { + if (set[i] && set[i] != WINED3DSP_WRITEMASK_ALL) + { unsigned int size = 0; memset(reg_mask, 0, sizeof(reg_mask)); if(!(set[i] & WINED3DSP_WRITEMASK_0)) { @@ -3363,8 +3536,9 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_in HeapFree(GetProcessHeap(), 0, set); } -static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexshader, - IWineD3DPixelShader *pixelshader, const WineD3D_GL_Info *gl_info) +/* GL locking is done by the caller */ +static GLhandleARB generate_param_reorder_function(struct wined3d_shader_buffer *buffer, + IWineD3DVertexShader *vertexshader, IWineD3DPixelShader *pixelshader, const struct wined3d_gl_info *gl_info) { GLhandleARB ret = 0; IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) vertexshader; @@ -3373,142 +3547,145 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs DWORD vs_major = vs->baseShader.reg_maps.shader_version.major; DWORD ps_major = ps ? ps->baseShader.reg_maps.shader_version.major : 0; unsigned int i; - SHADER_BUFFER buffer; - DWORD usage, usage_idx, writemask; + const char *semantic_name; + UINT semantic_idx; char reg_mask[6]; - const struct wined3d_shader_semantic *semantics_out; + const struct wined3d_shader_signature_element *output_signature; - shader_buffer_init(&buffer); + shader_buffer_clear(buffer); - shader_addline(&buffer, "#version 120\n"); + 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. * 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"); + if (((GLINFO_LOCATION).quirks & WINED3D_QUIRK_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, "gl_TexCoord[%u].w = 1.0;\n", i); } } - shader_addline(&buffer, "}\n"); + shader_addline(buffer, "}\n"); } else { - shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n"); + shader_addline(buffer, "void order_ps_input() { /* do nothing */ }\n"); } } else if(ps_major < 3 && vs_major >= 3) { + WORD map = vs->baseShader.reg_maps.output_registers; + /* The vertex shader writes to its own varyings, the pixel shader needs them in the builtin ones */ - semantics_out = vs->semantics_out; + output_signature = vs->output_signature; - shader_addline(&buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT); - for(i = 0; i < MAX_REG_OUTPUT; i++) { - if (!vs->baseShader.reg_maps.packed_output[i]) continue; + shader_addline(buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT); + for (i = 0; map; map >>= 1, ++i) + { + DWORD write_mask; - usage = semantics_out[i].usage; - usage_idx = semantics_out[i].usage_idx; - writemask = shader_glsl_get_write_mask(&semantics_out[i].reg, reg_mask); + if (!(map & 1)) continue; - switch(usage) { - case WINED3DDECLUSAGE_COLOR: - if (usage_idx == 0) - shader_addline(&buffer, "gl_FrontColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); - else if (usage_idx == 1) - shader_addline(&buffer, "gl_FrontSecondaryColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); - break; + semantic_name = output_signature[i].semantic_name; + semantic_idx = output_signature[i].semantic_idx; + write_mask = output_signature[i].mask; + shader_glsl_write_mask_to_str(write_mask, reg_mask); - case WINED3DDECLUSAGE_POSITION: - shader_addline(&buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); - break; + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if (semantic_idx == 0) + shader_addline(buffer, "gl_FrontColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + else if (semantic_idx == 1) + shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if (semantic_idx < 8) + { + if (!((GLINFO_LOCATION).quirks & WINED3D_QUIRK_SET_TEXCOORD_W) || ps_major > 0) + write_mask |= WINED3DSP_WRITEMASK_3; - 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); - if(!(writemask & WINED3DSP_WRITEMASK_3)) { - shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", usage_idx); - } - } - break; - - case WINED3DDECLUSAGE_PSIZE: - shader_addline(&buffer, "gl_PointSize = OUT[%u].x;\n", i); - break; - - case WINED3DDECLUSAGE_FOG: - shader_addline(&buffer, "gl_FogFragCoord = OUT[%u].%c;\n", i, reg_mask[1]); - break; - - default: - break; + shader_addline(buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n", + semantic_idx, reg_mask, i, reg_mask); + if (!(write_mask & WINED3DSP_WRITEMASK_3)) + shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx); + } + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + shader_addline(buffer, "gl_FogFragCoord = OUT[%u].%c;\n", i, reg_mask[1]); } } - shader_addline(&buffer, "}\n"); + shader_addline(buffer, "}\n"); } else if(ps_major >= 3 && vs_major >= 3) { - semantics_out = vs->semantics_out; + WORD map = vs->baseShader.reg_maps.output_registers; + + output_signature = vs->output_signature; /* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */ - 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); + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info)); + 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 */ - for(i = 0; i < MAX_REG_OUTPUT; i++) { - if (!vs->baseShader.reg_maps.packed_output[i]) continue; + for (i = 0; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; - usage = semantics_out[i].usage; - usage_idx = semantics_out[i].usage_idx; - shader_glsl_get_write_mask(&semantics_out[i].reg, reg_mask); + semantic_name = output_signature[i].semantic_name; + shader_glsl_write_mask_to_str(output_signature[i].mask, reg_mask); - switch(usage) { - case WINED3DDECLUSAGE_POSITION: - shader_addline(&buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); - break; - - case WINED3DDECLUSAGE_PSIZE: - shader_addline(&buffer, "gl_PointSize = OUT[%u].x;\n", i); - break; - - default: - break; + if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask); + } + else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i); } } /* Then, fix the pixel shader input */ - handle_ps3_input(&buffer, gl_info, ps->input_reg_map, - ps->semantics_in, &ps->baseShader.reg_maps, semantics_out, &vs->baseShader.reg_maps); + handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->input_signature, + &ps->baseShader.reg_maps, output_signature, &vs->baseShader.reg_maps); - shader_addline(&buffer, "}\n"); + shader_addline(buffer, "}\n"); } else if(ps_major >= 3 && vs_major < 3) { - shader_addline(&buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); - shader_addline(&buffer, "void order_ps_input() {\n"); + shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info)); + 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 * read gl_TexCoord and gl_ColorX, otherwise we'll run out of varyings */ - handle_ps3_input(&buffer, gl_info, ps->input_reg_map, ps->semantics_in, &ps->baseShader.reg_maps, NULL, NULL); - shader_addline(&buffer, "}\n"); + handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->input_signature, + &ps->baseShader.reg_maps, NULL, NULL); + shader_addline(buffer, "}\n"); } else { ERR("Unexpected vertex and pixel shader version condition: vs: %d, ps: %d\n", vs_major, ps_major); } ret = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); checkGLcall("glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)"); - GL_EXTCALL(glShaderSourceARB(ret, 1, (const char**)&buffer.buffer, NULL)); - checkGLcall("glShaderSourceARB(ret, 1, &buffer.buffer, NULL)"); + GL_EXTCALL(glShaderSourceARB(ret, 1, (const char**)&buffer->buffer, NULL)); + checkGLcall("glShaderSourceARB(ret, 1, &buffer->buffer, NULL)"); GL_EXTCALL(glCompileShaderARB(ret)); checkGLcall("glCompileShaderARB(ret)"); - shader_buffer_free(&buffer); return ret; } -static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD3D_GL_Info *gl_info, +/* GL locking is done by the caller */ +static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info, GLhandleARB programId, char prefix) { const local_constant *lconst; @@ -3522,7 +3699,299 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, value)); } - checkGLcall("Hardcoding local constants\n"); + checkGLcall("Hardcoding local constants"); +} + +/* GL locking is done by the caller */ +static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DPixelShaderImpl *This, + const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info) +{ + const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + const struct wined3d_gl_info *gl_info = context->gl_info; + CONST DWORD *function = This->baseShader.function; + struct shader_glsl_ctx_priv priv_ctx; + + /* Create the hw GLSL shader object and assign it as the shader->prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_ps_args = args; + priv_ctx.cur_np2fixup_info = np2fixup_info; + + shader_addline(buffer, "#version 120\n"); + + if(GL_SUPPORT(ARB_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) { + shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : 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(context, buffer, (IWineD3DBaseShader *)This, reg_maps, &priv_ctx); + + /* Pack 3.0 inputs */ + if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader) + { + shader_glsl_input_pack((IWineD3DPixelShader *) This, buffer, This->input_signature, reg_maps, args->vp_mode); + } + + /* Base Shader Body */ + shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); + + /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ + if (reg_maps->shader_version.major < 2) + { + /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */ + shader_addline(buffer, "gl_FragData[0] = R0;\n"); + } + + if (args->srgb_correction) + { + shader_addline(buffer, "tmp0.xyz = pow(gl_FragData[0].xyz, vec3(srgb_const0.x));\n"); + shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n"); + shader_addline(buffer, "tmp1.xyz = gl_FragData[0].xyz * vec3(srgb_const0.w);\n"); + shader_addline(buffer, "bvec3 srgb_compare = lessThan(gl_FragData[0].xyz, vec3(srgb_const1.x));\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n"); + shader_addline(buffer, "gl_FragData[0] = clamp(gl_FragData[0], 0.0, 1.0);\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 (reg_maps->shader_version.major < 3) + { + switch(args->fog) { + case FOG_OFF: break; + case FOG_LINEAR: + shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n"); + shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n"); + shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + case FOG_EXP: + /* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */ + shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n"); + shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + case FOG_EXP2: + /* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */ + shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n"); + shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); + shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n"); + break; + } + } + + 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 */ + return shader_obj; +} + +/* GL locking is done by the caller */ +static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DVertexShaderImpl *This, + const struct vs_compile_args *args) +{ + const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + const struct wined3d_gl_info *gl_info = context->gl_info; + CONST DWORD *function = This->baseShader.function; + struct shader_glsl_ctx_priv priv_ctx; + + /* Create the hw GLSL shader program and assign it as the shader->prgId */ + GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + + shader_addline(buffer, "#version 120\n"); + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_vs_args = args; + + /* Base Declarations */ + shader_generate_glsl_declarations(context, buffer, (IWineD3DBaseShader *)This, reg_maps, &priv_ctx); + + /* Base Shader Body */ + shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx); + + /* Unpack 3.0 outputs */ + if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n"); + else shader_addline(buffer, "order_ps_input();\n"); + + /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used + * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), + * the fog frag coord is thrown away. If the fog frag coord is used, but not written by + * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) + */ + if(args->fog_src == VS_FOG_Z) { + shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n"); + } else if (!reg_maps->fog) { + shader_addline(buffer, "gl_FogFragCoord = 0.0;\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"); + shader_addline(buffer, "gl_ClipVertex = gl_Position;\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); + + return shader_obj; +} + +static GLhandleARB find_glsl_pshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DPixelShaderImpl *shader, + const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info) +{ + UINT i; + DWORD new_size; + struct glsl_ps_compiled_shader *new_array; + struct glsl_pshader_private *shader_data; + struct ps_np2fixup_info *np2fixup = NULL; + GLhandleARB ret; + + if(!shader->backend_priv) { + shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + } + shader_data = shader->backend_priv; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) { + if(args->np2_fixup) *np2fixup_info = &shader_data->gl_shaders[i].np2fixup; + return shader_data->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + memset(&shader_data->gl_shaders[shader_data->num_gl_shaders].np2fixup, 0, sizeof(struct ps_np2fixup_info)); + if (args->np2_fixup) np2fixup = &shader_data->gl_shaders[shader_data->num_gl_shaders].np2fixup; + + pixelshader_update_samplers(&shader->baseShader.reg_maps, + ((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures); + + shader_buffer_clear(buffer); + ret = shader_glsl_generate_pshader(context, buffer, shader, args, np2fixup); + shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret; + *np2fixup_info = np2fixup; + + return ret; +} + +static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, + const DWORD use_map) { + if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; + return stored->fog_src == new->fog_src; +} + +static GLhandleARB find_glsl_vshader(const struct wined3d_context *context, + struct wined3d_shader_buffer *buffer, IWineD3DVertexShaderImpl *shader, + const struct vs_compile_args *args) +{ + UINT i; + DWORD new_size; + struct glsl_vs_compiled_shader *new_array; + DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; + struct glsl_vshader_private *shader_data; + GLhandleARB ret; + + if(!shader->backend_priv) { + shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); + } + shader_data = shader->backend_priv; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader_data->num_gl_shaders; i++) { + if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) { + return shader_data->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); + + if(shader_data->shader_array_size == shader_data->num_gl_shaders) { + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders, + new_size * sizeof(*shader_data->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader_data->gl_shaders = new_array; + shader_data->shader_array_size = new_size; + } + + shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args; + + shader_buffer_clear(buffer); + ret = shader_glsl_generate_vshader(context, buffer, shader, args); + shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret; + + return ret; } /** Sets the GLSL program ID for the given pixel and vertex shader combination. @@ -3533,33 +4002,26 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD * the program in the hash table. If it creates a program, it will link the * given objects, too. */ -static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use_vs) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - struct shader_glsl_priv *priv = This->shader_priv; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - IWineD3DPixelShader *pshader = This->stateBlock->pixelShader; - IWineD3DVertexShader *vshader = This->stateBlock->vertexShader; + +/* GL locking is done by the caller */ +static void set_glsl_shader_program(const struct wined3d_context *context, + IWineD3DDeviceImpl *device, BOOL use_ps, BOOL use_vs) +{ + IWineD3DVertexShader *vshader = use_vs ? device->stateBlock->vertexShader : NULL; + IWineD3DPixelShader *pshader = use_ps ? device->stateBlock->pixelShader : NULL; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct shader_glsl_priv *priv = device->shader_priv; struct glsl_shader_prog_link *entry = NULL; GLhandleARB programId = 0; GLhandleARB reorder_shader_id = 0; unsigned int i; char glsl_name[8]; - GLhandleARB vshader_id, pshader_id; struct ps_compile_args ps_compile_args; struct vs_compile_args vs_compile_args; - if(use_vs) { - find_vs_compile_args((IWineD3DVertexShaderImpl*)This->stateBlock->vertexShader, This->stateBlock, &vs_compile_args); - } else { - /* FIXME: Do we really have to spend CPU cycles to generate a few zeroed bytes? */ - memset(&vs_compile_args, 0, sizeof(vs_compile_args)); - } - if(use_ps) { - find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelShader, This->stateBlock, &ps_compile_args); - } else { - /* FIXME: Do we really have to spend CPU cycles to generate a few zeroed bytes? */ - memset(&ps_compile_args, 0, sizeof(ps_compile_args)); - } + if (vshader) find_vs_compile_args((IWineD3DVertexShaderImpl *)vshader, device->stateBlock, &vs_compile_args); + if (pshader) find_ps_compile_args((IWineD3DPixelShaderImpl *)pshader, device->stateBlock, &ps_compile_args); + entry = get_glsl_program_entry(priv, vshader, pshader, &vs_compile_args, &ps_compile_args); if (entry) { priv->glsl_program = entry; @@ -3578,24 +4040,22 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use entry->vs_args = vs_compile_args; entry->ps_args = ps_compile_args; entry->constant_version = 0; + entry->np2Fixup_info = NULL; /* Add the hash table entry */ add_glsl_program_entry(priv, entry); /* Set the current program */ priv->glsl_program = entry; - if(use_vs) { - vshader_id = find_gl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args); - } else { - vshader_id = 0; - } - /* Attach GLSL vshader */ - if (vshader_id) { - const unsigned int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */ + if (vshader) + { + GLhandleARB vshader_id = find_glsl_vshader(context, &priv->shader_buffer, + (IWineD3DVertexShaderImpl *)vshader, &vs_compile_args); + WORD map = ((IWineD3DBaseShaderImpl *)vshader)->baseShader.reg_maps.input_registers; char tmp_name[10]; - reorder_shader_id = generate_param_reorder_function(vshader, pshader, gl_info); + reorder_shader_id = generate_param_reorder_function(&priv->shader_buffer, 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"); @@ -3617,25 +4077,23 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use * We have to do this here because we need to know the Program ID * in order to make the bindings work, and it has to be done prior * to linking the GLSL program. */ - for (i = 0; i < max_attribs; ++i) { - if (((IWineD3DBaseShaderImpl*)vshader)->baseShader.reg_maps.attributes[i]) { - snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i); - GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); - } + for (i = 0; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; + + snprintf(tmp_name, sizeof(tmp_name), "attrib%u", i); + GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); } checkGLcall("glBindAttribLocationARB"); list_add_head(&((IWineD3DBaseShaderImpl *)vshader)->baseShader.linked_programs, &entry->vshader_entry); } - if(use_ps) { - pshader_id = find_gl_pshader((IWineD3DPixelShaderImpl *) pshader, &ps_compile_args); - } else { - pshader_id = 0; - } - /* Attach GLSL pshader */ - if (pshader_id) { + if (pshader) + { + GLhandleARB pshader_id = find_glsl_pshader(context, &priv->shader_buffer, + (IWineD3DPixelShaderImpl *)pshader, &ps_compile_args, &entry->np2Fixup_info); TRACE("Attaching GLSL shader object %u to program %u\n", pshader_id, programId); GL_EXTCALL(glAttachObjectARB(programId, pshader_id)); checkGLcall("glAttachObjectARB"); @@ -3668,25 +4126,22 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use } if(pshader) { - for(i = 0; i < ((IWineD3DPixelShaderImpl*)pshader)->numbumpenvmatconsts; i++) { - char name[32]; - sprintf(name, "bumpenvmat%d", ((IWineD3DPixelShaderImpl*)pshader)->bumpenvmatconst[i].texunit); + char name[32]; + + for(i = 0; i < MAX_TEXTURES; i++) { + sprintf(name, "bumpenvmat%u", i); entry->bumpenvmat_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); - sprintf(name, "luminancescale%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit); + sprintf(name, "luminancescale%u", i); entry->luminancescale_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); - sprintf(name, "luminanceoffset%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit); + sprintf(name, "luminanceoffset%u", i); entry->luminanceoffset_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); } - } - if (use_ps && ps_compile_args.np2_fixup) { - char name[32]; - for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (ps_compile_args.np2_fixup & (1 << i)) { - sprintf(name, "PsamplerNP2Fixup%u", i); - entry->np2Fixup_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + if (ps_compile_args.np2_fixup) { + if (entry->np2Fixup_info) { + entry->np2Fixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "PsamplerNP2Fixup")); } else { - entry->np2Fixup_location[i] = -1; + FIXME("NP2 texcoord fixup needed for this pixelshader, but no fixup uniform found.\n"); } } } @@ -3697,7 +4152,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use if (pshader && ((IWineD3DPixelShaderImpl *)pshader)->baseShader.reg_maps.shader_version.major >= 3 - && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > GL_LIMITS(glsl_varyings) / 4) + && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > vec4_varyings(3, gl_info)) { TRACE("Shader %d needs vertex color clamping disabled\n", programId); entry->vertex_color_clamp = GL_FALSE; @@ -3717,14 +4172,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use * fixed function fragment processing setups. So once the program is linked these samplers * won't change. */ - if(vshader_id) { - /* Load vertex shader samplers */ - shader_glsl_load_vsamplers(gl_info, This->texUnitMap, programId); - } - if(pshader_id) { - /* Load pixel shader samplers */ - shader_glsl_load_psamplers(gl_info, This->texUnitMap, programId); - } + if (vshader) shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId); + if (pshader) shader_glsl_load_psamplers(gl_info, device->texUnitMap, 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 @@ -3738,7 +4187,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use } } -static GLhandleARB create_glsl_blt_shader(const WineD3D_GL_Info *gl_info, enum tex_types tex_type) +/* GL locking is done by the caller */ +static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; @@ -3812,16 +4262,18 @@ static GLhandleARB create_glsl_blt_shader(const WineD3D_GL_Info *gl_info, enum t return program_id; } -static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - struct shader_glsl_priv *priv = This->shader_priv; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; +/* GL locking is done by the caller */ +static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) +{ + IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct shader_glsl_priv *priv = device->shader_priv; 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); + if (useVS || usePS) set_glsl_shader_program(context, device, usePS, useVS); else priv->glsl_program = NULL; current_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vertex_color_clamp : GL_FIXED_ONLY_ARB; @@ -3839,11 +4291,20 @@ static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { if (program_id) TRACE("Using GLSL program %u\n", program_id); GL_EXTCALL(glUseProgramObjectARB(program_id)); checkGLcall("glUseProgramObjectARB"); + + /* In case that NP2 texcoord fixup data is found for the selected program, trigger a reload of the + * constants. This has to be done because it can't be guaranteed that sampler() (from state.c) is + * called between selecting the shader and using it, which results in wrong fixup for some frames. */ + if (priv->glsl_program && priv->glsl_program->np2Fixup_info) + { + shader_glsl_load_np2fixup_constants((IWineD3DDevice *)device, usePS, useVS); + } } +/* GL locking is done by the caller */ static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; struct shader_glsl_priv *priv = This->shader_priv; GLhandleARB *blt_program = &priv->depth_blt_program[tex_type]; @@ -3858,9 +4319,10 @@ static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types t } } +/* GL locking is done by the caller */ static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; struct shader_glsl_priv *priv = This->shader_priv; GLhandleARB program_id; @@ -3876,7 +4338,8 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; struct shader_glsl_priv *priv = device->shader_priv; - const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + const struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; IWineD3DPixelShaderImpl *ps = NULL; IWineD3DVertexShaderImpl *vs = NULL; @@ -3886,15 +4349,45 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type); if(pshader) { + struct glsl_pshader_private *shader_data; ps = (IWineD3DPixelShaderImpl *) This; - if(ps->num_gl_shaders == 0) return; + shader_data = ps->backend_priv; + if(!shader_data || shader_data->num_gl_shaders == 0) + { + HeapFree(GetProcessHeap(), 0, shader_data); + ps->backend_priv = NULL; + return; + } + + context = ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + gl_info = context->gl_info; + if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface) - shader_glsl_select(This->baseShader.device, FALSE, FALSE); + { + ENTER_GL(); + shader_glsl_select(context, FALSE, FALSE); + LEAVE_GL(); + } } else { + struct glsl_vshader_private *shader_data; vs = (IWineD3DVertexShaderImpl *) This; - if(vs->num_gl_shaders == 0) return; + shader_data = vs->backend_priv; + if(!shader_data || shader_data->num_gl_shaders == 0) + { + HeapFree(GetProcessHeap(), 0, shader_data); + vs->backend_priv = NULL; + return; + } + + context = ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + gl_info = context->gl_info; + if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface) - shader_glsl_select(This->baseShader.device, FALSE, FALSE); + { + ENTER_GL(); + shader_glsl_select(context, FALSE, FALSE); + LEAVE_GL(); + } } linked_programs = &This->baseShader.linked_programs; @@ -3903,6 +4396,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { if (linked_programs->next) { struct glsl_shader_prog_link *entry, *entry2; + ENTER_GL(); if(pshader) { LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { delete_glsl_program_entry(priv, gl_info, entry); @@ -3912,62 +4406,57 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { delete_glsl_program_entry(priv, gl_info, entry); } } + LEAVE_GL(); } if(pshader) { UINT i; + struct glsl_pshader_private *shader_data = ps->backend_priv; ENTER_GL(); - for(i = 0; i < ps->num_gl_shaders; i++) { - TRACE("deleting pshader %u\n", ps->gl_shaders[i].prgId); - GL_EXTCALL(glDeleteObjectARB(ps->gl_shaders[i].prgId)); + for(i = 0; i < shader_data->num_gl_shaders; i++) { + TRACE("deleting pshader %u\n", shader_data->gl_shaders[i].prgId); + GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId)); checkGLcall("glDeleteObjectARB"); } LEAVE_GL(); - HeapFree(GetProcessHeap(), 0, ps->gl_shaders); - ps->gl_shaders = NULL; - ps->num_gl_shaders = 0; - ps->shader_array_size = 0; + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + HeapFree(GetProcessHeap(), 0, shader_data); + ps->backend_priv = NULL; } else { UINT i; + struct glsl_vshader_private *shader_data = vs->backend_priv; ENTER_GL(); - for(i = 0; i < vs->num_gl_shaders; i++) { - TRACE("deleting vshader %u\n", vs->gl_shaders[i].prgId); - GL_EXTCALL(glDeleteObjectARB(vs->gl_shaders[i].prgId)); + for(i = 0; i < shader_data->num_gl_shaders; i++) { + TRACE("deleting vshader %u\n", shader_data->gl_shaders[i].prgId); + GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId)); checkGLcall("glDeleteObjectARB"); } LEAVE_GL(); - HeapFree(GetProcessHeap(), 0, vs->gl_shaders); - vs->gl_shaders = NULL; - vs->num_gl_shaders = 0; - vs->shader_array_size = 0; + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); + HeapFree(GetProcessHeap(), 0, shader_data); + vs->backend_priv = NULL; } } -static unsigned int glsl_program_key_hash(const void *key) +static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry) { const glsl_program_key_t *k = key; + const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry, + const struct glsl_shader_prog_link, program_lookup_entry); + int cmp; - unsigned int hash = ((DWORD_PTR) k->vshader) | ((DWORD_PTR) k->pshader) << 16; - hash += ~(hash << 15); - hash ^= (hash >> 10); - hash += (hash << 3); - hash ^= (hash >> 6); - hash += ~(hash << 11); - hash ^= (hash >> 16); + if (k->vshader > prog->vshader) return 1; + else if (k->vshader < prog->vshader) return -1; - return hash; -} + if (k->pshader > prog->pshader) return 1; + else if (k->pshader < prog->pshader) return -1; -static BOOL glsl_program_key_compare(const void *keya, const void *keyb) -{ - const glsl_program_key_t *ka = keya; - const glsl_program_key_t *kb = keyb; + if (k->vshader && (cmp = memcmp(&k->vs_args, &prog->vs_args, sizeof(prog->vs_args)))) return cmp; + if (k->pshader && (cmp = memcmp(&k->ps_args, &prog->ps_args, sizeof(prog->ps_args)))) return cmp; - return ka->vshader == kb->vshader && ka->pshader == kb->pshader && - (memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0) && - (memcmp(&ka->vs_args, &kb->vs_args, sizeof(kb->vs_args)) == 0); + return 0; } static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count) @@ -3994,50 +4483,73 @@ static void constant_heap_free(struct constant_heap *heap) HeapFree(GetProcessHeap(), 0, heap->entries); } +static const struct wine_rb_functions wined3d_glsl_program_rb_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + glsl_program_key_compare, +}; + static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv)); SIZE_T stack_size = wined3d_log2i(max(GL_LIMITS(vshader_constantsF), GL_LIMITS(pshader_constantsF))) + 1; + if (!shader_buffer_init(&priv->shader_buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + goto fail; + } + priv->stack = HeapAlloc(GetProcessHeap(), 0, stack_size * sizeof(*priv->stack)); if (!priv->stack) { ERR("Failed to allocate memory.\n"); - HeapFree(GetProcessHeap(), 0, priv); - return E_OUTOFMEMORY; + goto fail; } if (!constant_heap_init(&priv->vconst_heap, GL_LIMITS(vshader_constantsF))) { ERR("Failed to initialize vertex shader constant heap\n"); - HeapFree(GetProcessHeap(), 0, priv->stack); - HeapFree(GetProcessHeap(), 0, priv); - return E_OUTOFMEMORY; + goto fail; } if (!constant_heap_init(&priv->pconst_heap, GL_LIMITS(pshader_constantsF))) { ERR("Failed to initialize pixel shader constant heap\n"); - constant_heap_free(&priv->vconst_heap); - HeapFree(GetProcessHeap(), 0, priv->stack); - HeapFree(GetProcessHeap(), 0, priv); - return E_OUTOFMEMORY; + goto fail; + } + + if (wine_rb_init(&priv->program_lookup, &wined3d_glsl_program_rb_functions) == -1) + { + ERR("Failed to initialize rbtree.\n"); + goto fail; } - priv->glsl_program_lookup = hash_table_create(glsl_program_key_hash, glsl_program_key_compare); priv->next_constant_version = 1; This->shader_priv = priv; return WINED3D_OK; + +fail: + constant_heap_free(&priv->pconst_heap); + constant_heap_free(&priv->vconst_heap); + HeapFree(GetProcessHeap(), 0, priv->stack); + shader_buffer_free(&priv->shader_buffer); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; } +/* Context activation is done by the caller. */ static void shader_glsl_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; struct shader_glsl_priv *priv = This->shader_priv; int i; + ENTER_GL(); for (i = 0; i < tex_type_count; ++i) { if (priv->depth_blt_program[i]) @@ -4045,10 +4557,12 @@ static void shader_glsl_free(IWineD3DDevice *iface) { GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program[i])); } } + LEAVE_GL(); - hash_table_destroy(priv->glsl_program_lookup, NULL, NULL); + wine_rb_destroy(&priv->program_lookup, NULL, NULL); constant_heap_free(&priv->pconst_heap); constant_heap_free(&priv->vconst_heap); + HeapFree(GetProcessHeap(), 0, priv->stack); HeapFree(GetProcessHeap(), 0, This->shader_priv); This->shader_priv = NULL; @@ -4059,185 +4573,19 @@ static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) { return FALSE; } -static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, - SHADER_BUFFER *buffer, const struct ps_compile_args *args) -{ - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; - const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; - CONST DWORD *function = This->baseShader.function; - const char *fragcolor; - const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; - - /* Create the hw GLSL shader object and assign it as the shader->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_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) { - shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : 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, args); - - /* Pack 3.0 inputs */ - if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader) - { - pshader_glsl_input_pack(iface, buffer, This->semantics_in, reg_maps, args->vp_mode); - } - - /* Base Shader Body */ - shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function); - - /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ - if (reg_maps->shader_version.major < 2) - { - /* 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(args->srgb_correction) { - 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 (reg_maps->shader_version.major < 3) - { - switch(args->fog) { - case FOG_OFF: break; - case FOG_LINEAR: - shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n"); - shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n"); - shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n"); - shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); - break; - case FOG_EXP: - /* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */ - shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n"); - shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); - shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); - break; - case FOG_EXP2: - /* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */ - shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n"); - shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n"); - shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); - break; - } - } - - 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 */ - return shader_obj; -} - -static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args) -{ - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; - CONST DWORD *function = This->baseShader.function; - const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; - - /* Create the hw GLSL shader program and assign it as the shader->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, NULL); - - /* Base Shader Body */ - shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function); - - /* Unpack 3.0 outputs */ - if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n"); - else shader_addline(buffer, "order_ps_input();\n"); - - /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used - * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), - * the fog frag coord is thrown away. If the fog frag coord is used, but not written by - * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) - */ - if(args->fog_src == VS_FOG_Z) { - shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n"); - } else if (!reg_maps->fog) { - shader_addline(buffer, "gl_FogFragCoord = 0.0;\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); - - return shader_obj; -} - -static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps) +static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, + const struct 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. + * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support based + * on the version of 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)) + if ((gl_info->supported[NV_VERTEX_PROGRAM2] && !gl_info->supported[NV_VERTEX_PROGRAM3]) + || gl_info->ps_arb_max_instructions <= 512) pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0); else pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0); @@ -4255,7 +4603,8 @@ static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info * * 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)) + if ((gl_info->supported[NV_FRAGMENT_PROGRAM] && !gl_info->supported[NV_FRAGMENT_PROGRAM2]) + || (gl_info->ps_arb_max_instructions <= 512)) pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0); else pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0); @@ -4276,6 +4625,8 @@ static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info * */ pCaps->PixelShader1xMaxValue = 8.0; TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (pCaps->PixelShaderVersion >> 8) & 0xff, pCaps->PixelShaderVersion & 0xff); + + pCaps->VSClipping = TRUE; } static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup) @@ -4301,7 +4652,7 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB { /* WINED3DSIH_ABS */ shader_glsl_map2gl, /* WINED3DSIH_ADD */ shader_glsl_arith, - /* WINED3DSIH_BEM */ pshader_glsl_bem, + /* WINED3DSIH_BEM */ shader_glsl_bem, /* WINED3DSIH_BREAK */ shader_glsl_break, /* WINED3DSIH_BREAKC */ shader_glsl_breakc, /* WINED3DSIH_BREAKP */ NULL, @@ -4314,7 +4665,7 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB /* WINED3DSIH_DEF */ NULL, /* WINED3DSIH_DEFB */ NULL, /* WINED3DSIH_DEFI */ NULL, - /* WINED3DSIH_DP2ADD */ pshader_glsl_dp2add, + /* WINED3DSIH_DP2ADD */ shader_glsl_dp2add, /* WINED3DSIH_DP3 */ shader_glsl_dot, /* WINED3DSIH_DP4 */ shader_glsl_dot, /* WINED3DSIH_DST */ shader_glsl_dst, @@ -4352,7 +4703,7 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB /* WINED3DSIH_POW */ shader_glsl_pow, /* WINED3DSIH_RCP */ shader_glsl_rcp, /* WINED3DSIH_REP */ shader_glsl_rep, - /* WINED3DSIH_RET */ NULL, + /* WINED3DSIH_RET */ shader_glsl_ret, /* WINED3DSIH_RSQ */ shader_glsl_rsq, /* WINED3DSIH_SETP */ NULL, /* WINED3DSIH_SGE */ shader_glsl_compare, @@ -4360,32 +4711,49 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB /* WINED3DSIH_SINCOS */ shader_glsl_sincos, /* WINED3DSIH_SLT */ shader_glsl_compare, /* WINED3DSIH_SUB */ shader_glsl_arith, - /* WINED3DSIH_TEX */ pshader_glsl_tex, - /* WINED3DSIH_TEXBEM */ pshader_glsl_texbem, - /* WINED3DSIH_TEXBEML */ pshader_glsl_texbem, - /* WINED3DSIH_TEXCOORD */ pshader_glsl_texcoord, - /* WINED3DSIH_TEXDEPTH */ pshader_glsl_texdepth, - /* WINED3DSIH_TEXDP3 */ pshader_glsl_texdp3, - /* WINED3DSIH_TEXDP3TEX */ pshader_glsl_texdp3tex, - /* WINED3DSIH_TEXKILL */ pshader_glsl_texkill, + /* WINED3DSIH_TEX */ shader_glsl_tex, + /* WINED3DSIH_TEXBEM */ shader_glsl_texbem, + /* WINED3DSIH_TEXBEML */ shader_glsl_texbem, + /* WINED3DSIH_TEXCOORD */ shader_glsl_texcoord, + /* WINED3DSIH_TEXDEPTH */ shader_glsl_texdepth, + /* WINED3DSIH_TEXDP3 */ shader_glsl_texdp3, + /* WINED3DSIH_TEXDP3TEX */ shader_glsl_texdp3tex, + /* WINED3DSIH_TEXKILL */ shader_glsl_texkill, /* WINED3DSIH_TEXLDD */ shader_glsl_texldd, /* WINED3DSIH_TEXLDL */ shader_glsl_texldl, - /* WINED3DSIH_TEXM3x2DEPTH */ pshader_glsl_texm3x2depth, - /* WINED3DSIH_TEXM3x2PAD */ pshader_glsl_texm3x2pad, - /* WINED3DSIH_TEXM3x2TEX */ pshader_glsl_texm3x2tex, - /* WINED3DSIH_TEXM3x3 */ pshader_glsl_texm3x3, + /* WINED3DSIH_TEXM3x2DEPTH */ shader_glsl_texm3x2depth, + /* WINED3DSIH_TEXM3x2PAD */ shader_glsl_texm3x2pad, + /* WINED3DSIH_TEXM3x2TEX */ shader_glsl_texm3x2tex, + /* WINED3DSIH_TEXM3x3 */ shader_glsl_texm3x3, /* WINED3DSIH_TEXM3x3DIFF */ NULL, - /* WINED3DSIH_TEXM3x3PAD */ pshader_glsl_texm3x3pad, - /* WINED3DSIH_TEXM3x3SPEC */ pshader_glsl_texm3x3spec, - /* WINED3DSIH_TEXM3x3TEX */ pshader_glsl_texm3x3tex, - /* WINED3DSIH_TEXM3x3VSPEC */ pshader_glsl_texm3x3vspec, - /* WINED3DSIH_TEXREG2AR */ pshader_glsl_texreg2ar, - /* WINED3DSIH_TEXREG2GB */ pshader_glsl_texreg2gb, - /* WINED3DSIH_TEXREG2RGB */ pshader_glsl_texreg2rgb, + /* WINED3DSIH_TEXM3x3PAD */ shader_glsl_texm3x3pad, + /* WINED3DSIH_TEXM3x3SPEC */ shader_glsl_texm3x3spec, + /* WINED3DSIH_TEXM3x3TEX */ shader_glsl_texm3x3tex, + /* WINED3DSIH_TEXM3x3VSPEC */ shader_glsl_texm3x3vspec, + /* WINED3DSIH_TEXREG2AR */ shader_glsl_texreg2ar, + /* WINED3DSIH_TEXREG2GB */ shader_glsl_texreg2gb, + /* WINED3DSIH_TEXREG2RGB */ shader_glsl_texreg2rgb, }; +static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) { + SHADER_HANDLER hw_fct; + + /* Select handler */ + hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx]; + + /* Unhandled opcode */ + if (!hw_fct) + { + FIXME("Backend can't handle opcode %#x\n", ins->handler_idx); + return; + } + hw_fct(ins); + + shader_glsl_add_instruction_modifiers(ins); +} + const shader_backend_t glsl_shader_backend = { - shader_glsl_instruction_handler_table, + shader_glsl_handle_instruction, shader_glsl_select, shader_glsl_select_depth_blt, shader_glsl_deselect_depth_blt, @@ -4397,9 +4765,6 @@ const shader_backend_t glsl_shader_backend = { shader_glsl_alloc, shader_glsl_free, shader_glsl_dirty_const, - shader_glsl_generate_pshader, - shader_glsl_generate_vshader, shader_glsl_get_caps, shader_glsl_color_fixup_supported, - shader_glsl_add_instruction_modifiers, }; diff --git a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c index f7e331de3d4..a0a576be184 100644 --- a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c +++ b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c @@ -29,7 +29,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info -static void nvts_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + +/* GL locking for state handlers is done by the caller. */ + +static void nvts_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ BOOL bumpmap = FALSE; if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE || @@ -445,12 +449,12 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx); } - checkGLcall("set_tex_op_nvrc()\n"); - + checkGLcall("set_tex_op_nvrc()"); } -static void nvrc_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void nvrc_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage); @@ -542,7 +546,8 @@ static void nvrc_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3 } } -static void nvts_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void nvts_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD sampler = state - STATE_SAMPLER(0); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler]; @@ -557,7 +562,8 @@ static void nvts_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D nvts_activate_dimensions(sampler, stateblock, context); } -static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1]; float mat[2][2]; @@ -584,7 +590,8 @@ static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void nvrc_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void nvrc_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0])); @@ -592,9 +599,12 @@ static void nvrc_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine #undef GLINFO_LOCATION #define GLINFO_LOCATION (*gl_info) +/* Context activation is done by the caller. */ static void nvrc_enable(IWineD3DDevice *iface, BOOL enable) { } +/* Context activation is done by the caller. */ static void nvts_enable(IWineD3DDevice *iface, BOOL enable) { + ENTER_GL(); if(enable) { glEnable(GL_TEXTURE_SHADER_NV); checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); @@ -602,9 +612,11 @@ static void nvts_enable(IWineD3DDevice *iface, BOOL enable) { glDisable(GL_TEXTURE_SHADER_NV); checkGLcall("glDisable(GL_TEXTURE_SHADER_NV)"); } + LEAVE_GL(); } -static void nvrc_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) +static void nvrc_fragment_get_caps(WINED3DDEVTYPE devtype, + const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps) { pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | WINED3DTEXOPCAPS_ADDSIGNED | @@ -659,6 +671,7 @@ static void nvrc_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info } static HRESULT nvrc_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +/* Context activation is done by the caller. */ static void nvrc_fragment_free(IWineD3DDevice *iface) {} /* Two fixed function pipeline implementations using GL_NV_register_combiners and @@ -687,137 +700,137 @@ static BOOL nvts_color_fixup_supported(struct color_fixup_desc fixup) } static const struct StateEntryTemplate nvrc_fragmentstate_template[] = { - { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 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_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(0, WINED3DTSS_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(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(1, WINED3DTSS_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(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(2, WINED3DTSS_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(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(3, WINED3DTSS_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(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(4, WINED3DTSS_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(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(5, WINED3DTSS_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(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(6, WINED3DTSS_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(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, { STATE_TEXTURESTAGE(7, WINED3DTSS_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_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 }, - { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 }, - { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, - { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), nvrc_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), nvrc_texfactor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(0), { STATE_SAMPLER(0), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(2), { STATE_SAMPLER(2), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(3), { STATE_SAMPLER(3), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(4), { STATE_SAMPLER(4), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(5), { STATE_SAMPLER(5), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, { STATE_SAMPLER(6), { STATE_SAMPLER(6), nvts_texdim }, NV_TEXTURE_SHADER2 }, - { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, { 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 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; const struct fragment_pipeline nvts_fragment_pipeline = { diff --git a/reactos/dll/directx/wine/wined3d/palette.c b/reactos/dll/directx/wine/wined3d/palette.c index 338e66e0906..a5447d07335 100644 --- a/reactos/dll/directx/wine/wined3d/palette.c +++ b/reactos/dll/directx/wine/wined3d/palette.c @@ -22,7 +22,6 @@ #include "winerror.h" #include "wine/debug.h" -#include #include #include "wined3d_private.h" @@ -78,7 +77,9 @@ DWORD IWineD3DPaletteImpl_Size(DWORD dwFlags) { case WINEDDPCAPS_2BIT: return 4; case WINEDDPCAPS_4BIT: return 16; case WINEDDPCAPS_8BIT: return 256; - default: assert(0); return 256; + default: + FIXME("Unhandled size bits %#x.\n", dwFlags & SIZE_BITS); + return 256; } } diff --git a/reactos/dll/directx/wine/wined3d/pixelshader.c b/reactos/dll/directx/wine/wined3d/pixelshader.c index 33148c8b9b3..6ac145c1ae2 100644 --- a/reactos/dll/directx/wine/wined3d/pixelshader.c +++ b/reactos/dll/directx/wine/wined3d/pixelshader.c @@ -178,6 +178,10 @@ static void pshader_set_limits(IWineD3DPixelShaderImpl *This) This->baseShader.limits.label = 16; break; + case WINED3D_SHADER_VERSION(4,0): + FIXME("Using 3.0 limits for 4.0 shader\n"); + /* Fall through */ + case WINED3D_SHADER_VERSION(3,0): This->baseShader.limits.temporary = 32; This->baseShader.limits.constant_float = 224; @@ -238,8 +242,9 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i list_init(&This->baseShader.constantsI); /* Second pass: figure out which registers are used, what the semantics are, etc.. */ - hr = shader_get_registers_used((IWineD3DBaseShader *)This, fe, reg_maps, This->semantics_in, NULL, pFunction, - GL_LIMITS(pshader_constantsF)); + hr = shader_get_registers_used((IWineD3DBaseShader *)This, fe, + reg_maps, NULL, This->input_signature, NULL, + pFunction, GL_LIMITS(pshader_constantsF)); if (FAILED(hr)) return hr; pshader_set_limits(This); @@ -294,7 +299,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i return WINED3D_OK; } -static void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures) +void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures) { WINED3DSAMPLER_TEXTURE_TYPE *sampler_type = reg_maps->sampler_type; unsigned int i; @@ -338,29 +343,6 @@ static void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD } } -static GLuint pixelshader_compile(IWineD3DPixelShaderImpl *This, const struct ps_compile_args *args) -{ - CONST DWORD *function = This->baseShader.function; - GLuint retval; - SHADER_BUFFER buffer; - IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; - - TRACE("(%p) : function %p\n", This, function); - - pixelshader_update_samplers(&This->baseShader.reg_maps, - ((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->textures); - - /* Generate the HW shader */ - TRACE("(%p) : Generating hardware program\n", This); - This->cur_args = args; - shader_buffer_init(&buffer); - retval = device->shader_backend->shader_generate_pshader((IWineD3DPixelShader *)This, &buffer, args); - shader_buffer_free(&buffer); - This->cur_args = NULL; - - return retval; -} - const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl = { /*** IUnknown methods ***/ @@ -439,44 +421,3 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp } } } - -GLuint find_gl_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args) -{ - UINT i; - DWORD new_size; - struct ps_compiled_shader *new_array; - - /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), - * so a linear search is more performant than a hashmap or a binary search - * (cache coherency etc) - */ - for(i = 0; i < shader->num_gl_shaders; i++) { - if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) { - return shader->gl_shaders[i].prgId; - } - } - - TRACE("No matching GL shader found, compiling a new shader\n"); - if(shader->shader_array_size == shader->num_gl_shaders) { - if (shader->num_gl_shaders) - { - new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2); - new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders, - new_size * sizeof(*shader->gl_shaders)); - } else { - new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders)); - new_size = 1; - } - - if(!new_array) { - ERR("Out of memory\n"); - return 0; - } - shader->gl_shaders = new_array; - shader->shader_array_size = new_size; - } - - shader->gl_shaders[shader->num_gl_shaders].args = *args; - shader->gl_shaders[shader->num_gl_shaders].prgId = pixelshader_compile(shader, args); - return shader->gl_shaders[shader->num_gl_shaders++].prgId; -} diff --git a/reactos/dll/directx/wine/wined3d/query.c b/reactos/dll/directx/wine/wined3d/query.c index 481177f4e72..2a2c1b1ecb6 100644 --- a/reactos/dll/directx/wine/wined3d/query.c +++ b/reactos/dll/directx/wine/wined3d/query.c @@ -62,38 +62,22 @@ 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(); /* Queries are specific to the GL context that created them. Not * deleting the query will obviously leak it, but that's still better * than potentially deleting a different query with the same id in this * context, and (still) leaking the actual query. */ - if(This->type == WINED3DQUERYTYPE_EVENT) { - if (((WineQueryEventData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext - || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId()) - { - FIXME("Query was created in a different context, skipping deletion\n"); - } - else if(GL_SUPPORT(APPLE_FENCE)) - { - GL_EXTCALL(glDeleteFencesAPPLE(1, &((WineQueryEventData *)(This->extendedData))->fenceId)); - checkGLcall("glDeleteFencesAPPLE"); - } else if(GL_SUPPORT(NV_FENCE)) { - GL_EXTCALL(glDeleteFencesNV(1, &((WineQueryEventData *)(This->extendedData))->fenceId)); - checkGLcall("glDeleteFencesNV"); - } - } else if(This->type == WINED3DQUERYTYPE_OCCLUSION && GL_SUPPORT(ARB_OCCLUSION_QUERY)) { - if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext - || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId()) - { - FIXME("Query was created in a different context, skipping deletion\n"); - } - else - { - GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId)); - checkGLcall("glDeleteQueriesARB"); - } + if (This->type == WINED3DQUERYTYPE_EVENT) + { + struct wined3d_event_query *query = This->extendedData; + + if (query->context) context_free_event_query(query); + } + else if (This->type == WINED3DQUERYTYPE_OCCLUSION) + { + struct wined3d_occlusion_query *query = This->extendedData; + + if (query->context) context_free_occlusion_query(query); } - LEAVE_GL(); HeapFree(GetProcessHeap(), 0, This->extendedData); HeapFree(GetProcessHeap(), 0, This); @@ -286,7 +270,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; - GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId; + struct wined3d_occlusion_query *query = This->extendedData; DWORD* data = pData; GLuint available; GLuint samples; @@ -294,6 +278,8 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); + if (!query->context) This->state = QUERY_CREATED; + if (This->state == QUERY_CREATED) { /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */ @@ -316,26 +302,27 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, return S_OK; } - if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext - || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId()) + if (query->context->tid != GetCurrentThreadId()) { - FIXME("%p Wrong context, returning 1.\n", This); + FIXME("%p Wrong thread, returning 1.\n", This); *data = 1; return S_OK; } + ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); - GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); - checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n"); + GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)"); 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"); + GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_ARB, &samples)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); TRACE("(%p) : Returning %d samples.\n", This, samples); *data = samples; } @@ -353,32 +340,52 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; + struct wined3d_event_query *query = This->extendedData; 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 */ - FIXME("Query context not active, reporting GPU idle\n"); + if (!pData || !dwSize) return S_OK; + + if (!query->context) + { + ERR("Query not started, returning TRUE.\n"); *data = TRUE; - } else if(GL_SUPPORT(APPLE_FENCE)) { - ENTER_GL(); - *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId)); + + return S_OK; + } + + if (query->context->tid != GetCurrentThreadId()) + { + /* See comment in IWineD3DQuery::Issue, event query codeblock */ + FIXME("Wrong thread, reporting GPU idle.\n"); + *data = TRUE; + + return S_OK; + } + + ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + + ENTER_GL(); + + if (GL_SUPPORT(APPLE_FENCE)) + { + *data = GL_EXTCALL(glTestFenceAPPLE(query->id)); checkGLcall("glTestFenceAPPLE"); - LEAVE_GL(); - } else if(GL_SUPPORT(NV_FENCE)) { - ENTER_GL(); - *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId)); + } + else if (GL_SUPPORT(NV_FENCE)) + { + *data = GL_EXTCALL(glTestFenceNV(query->id)); checkGLcall("glTestFenceNV"); - LEAVE_GL(); - } else { + } + else + { WARN("(%p): reporting GPU idle\n", This); *data = TRUE; } + LEAVE_GL(); + return S_OK; } @@ -455,29 +462,47 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD 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(); + if (dwIssueFlags & WINED3DISSUE_END) + { + struct wined3d_event_query *query = This->extendedData; + struct wined3d_context *context; + + if (query->context) + { + if (query->context->tid != GetCurrentThreadId()) + { + context_free_event_query(query); + context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context_alloc_event_query(context, query); + } + else + { + ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + } } - } else if(dwIssueFlags & WINED3DISSUE_BEGIN) { + else + { + context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context_alloc_event_query(context, query); + } + + ENTER_GL(); + + if (GL_SUPPORT(APPLE_FENCE)) + { + GL_EXTCALL(glSetFenceAPPLE(query->id)); + checkGLcall("glSetFenceAPPLE"); + } + else if (GL_SUPPORT(NV_FENCE)) + { + GL_EXTCALL(glSetFenceNV(query->id, 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"); } @@ -494,35 +519,68 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD 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 (GL_SUPPORT(ARB_OCCLUSION_QUERY)) + { + struct wined3d_occlusion_query *query = This->extendedData; + struct wined3d_context *context; + + /* This is allowed according to msdn and our tests. Reset the query and restart */ + if (dwIssueFlags & WINED3DISSUE_BEGIN) + { + if (This->state == QUERY_BUILDING) + { + if (query->context->tid != GetCurrentThreadId()) + { + FIXME("Wrong thread, can't restart query.\n"); + + context_free_occlusion_query(query); + context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context_alloc_occlusion_query(context, query); + } + else + { + ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + + ENTER_GL(); + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + LEAVE_GL(); + } + } + else + { + if (query->context) context_free_occlusion_query(query); + context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context_alloc_occlusion_query(context, query); + } - if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { - FIXME("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()"); - } - } + GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id)); + checkGLcall("glBeginQuery()"); LEAVE_GL(); } + 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) + { + if (query->context->tid != GetCurrentThreadId()) + { + FIXME("Wrong thread, can't end query.\n"); + } + else + { + ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + + ENTER_GL(); + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + LEAVE_GL(); + } + } + } } else { FIXME("(%p) : Occlusion queries not supported\n", This); } diff --git a/reactos/dll/directx/wine/wined3d/resource.c b/reactos/dll/directx/wine/wined3d/resource.c index 807240bb333..89ea7f3794d 100644 --- a/reactos/dll/directx/wine/wined3d/resource.c +++ b/reactos/dll/directx/wine/wined3d/resource.c @@ -26,10 +26,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -HRESULT resource_init(struct IWineD3DResourceClass *resource, WINED3DRESOURCETYPE resource_type, +HRESULT resource_init(IWineD3DResource *iface, WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, WINED3DPOOL pool, IUnknown *parent) { + struct IWineD3DResourceClass *resource = &((IWineD3DResourceImpl *)iface)->resource; + resource->wineD3DDevice = device; resource->parent = parent; resource->resourceType = resource_type; @@ -68,6 +70,8 @@ HRESULT resource_init(struct IWineD3DResourceClass *resource, WINED3DRESOURCETYP WineD3DAdapterChangeGLRam(device, size); } + device_resource_add(device, iface); + return WINED3D_OK; } @@ -96,10 +100,7 @@ void resource_cleanup(IWineD3DResource *iface) This->resource.allocatedMemory = 0; This->resource.heapMemory = 0; - if (This->resource.wineD3DDevice != NULL) { - IWineD3DDevice_ResourceReleased((IWineD3DDevice *)This->resource.wineD3DDevice, iface); - }/* NOTE: this is not really an error for system memory resources */ - return; + if (This->resource.wineD3DDevice) device_resource_released(This->resource.wineD3DDevice, iface); } HRESULT resource_get_device(IWineD3DResource *iface, IWineD3DDevice** ppDevice) diff --git a/reactos/dll/directx/wine/wined3d/shader_sm1.c b/reactos/dll/directx/wine/wined3d/shader_sm1.c index a626d52a763..ead2769e34c 100644 --- a/reactos/dll/directx/wine/wined3d/shader_sm1.c +++ b/reactos/dll/directx/wine/wined3d/shader_sm1.c @@ -349,6 +349,7 @@ static void shader_parse_src_param(DWORD param, const struct wined3d_shader_src_ src->reg.type = ((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2); src->reg.idx = param & WINED3DSP_REGNUM_MASK; + src->reg.array_idx = ~0U; src->swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT; src->modifiers = (param & WINED3DSP_SRCMOD_MASK) >> WINED3DSP_SRCMOD_SHIFT; src->reg.rel_addr = rel_addr; @@ -360,6 +361,7 @@ static void shader_parse_dst_param(DWORD param, const struct wined3d_shader_src_ dst->reg.type = ((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2); dst->reg.idx = param & WINED3DSP_REGNUM_MASK; + dst->reg.array_idx = ~0U; dst->write_mask = (param & WINED3D_SM1_WRITEMASK_MASK) >> WINED3D_SM1_WRITEMASK_SHIFT; dst->modifiers = (param & WINED3DSP_DSTMOD_MASK) >> WINED3DSP_DSTMOD_SHIFT; dst->shift = (param & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; diff --git a/reactos/dll/directx/wine/wined3d/shader_sm4.c b/reactos/dll/directx/wine/wined3d/shader_sm4.c index 5cc445db69a..91aa882c888 100644 --- a/reactos/dll/directx/wine/wined3d/shader_sm4.c +++ b/reactos/dll/directx/wine/wined3d/shader_sm4.c @@ -28,6 +28,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); #define WINED3D_SM4_OPCODE_MASK 0xff +#define WINED3D_SM4_REGISTER_ORDER_SHIFT 20 +#define WINED3D_SM4_REGISTER_ORDER_MASK (0x3 << WINED3D_SM4_REGISTER_ORDER_SHIFT) + #define WINED3D_SM4_REGISTER_TYPE_SHIFT 12 #define WINED3D_SM4_REGISTER_TYPE_MASK (0xf << WINED3D_SM4_REGISTER_TYPE_SHIFT) @@ -46,19 +49,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); enum wined3d_sm4_opcode { WINED3D_SM4_OP_ADD = 0x00, + WINED3D_SM4_OP_DP3 = 0x10, + WINED3D_SM4_OP_DP4 = 0x11, WINED3D_SM4_OP_EXP = 0x19, + WINED3D_SM4_OP_LOG = 0x2f, + WINED3D_SM4_OP_MIN = 0x33, + WINED3D_SM4_OP_MAX = 0x34, WINED3D_SM4_OP_MOV = 0x36, WINED3D_SM4_OP_MUL = 0x38, WINED3D_SM4_OP_RET = 0x3e, + WINED3D_SM4_OP_RSQ = 0x44, WINED3D_SM4_OP_SINCOS = 0x4d, }; enum wined3d_sm4_register_type { - WINED3D_SM4_RT_TEMP = 0x0, - WINED3D_SM4_RT_INPUT = 0x1, - WINED3D_SM4_RT_OUTPUT = 0x2, - WINED3D_SM4_RT_IMMCONST = 0x4, + WINED3D_SM4_RT_TEMP = 0x0, + WINED3D_SM4_RT_INPUT = 0x1, + WINED3D_SM4_RT_OUTPUT = 0x2, + WINED3D_SM4_RT_IMMCONST = 0x4, + WINED3D_SM4_RT_CONSTBUFFER = 0x8, }; enum wined3d_sm4_immconst_type @@ -92,20 +102,30 @@ struct sysval_map static const struct wined3d_sm4_opcode_info opcode_table[] = { {WINED3D_SM4_OP_ADD, WINED3DSIH_ADD, 1, 2}, + {WINED3D_SM4_OP_DP3, WINED3DSIH_DP3, 1, 2}, + {WINED3D_SM4_OP_DP4, WINED3DSIH_DP4, 1, 2}, {WINED3D_SM4_OP_EXP, WINED3DSIH_EXP, 1, 1}, + {WINED3D_SM4_OP_LOG, WINED3DSIH_LOG, 1, 1}, + {WINED3D_SM4_OP_MIN, WINED3DSIH_MIN, 1, 2}, + {WINED3D_SM4_OP_MAX, WINED3DSIH_MAX, 1, 2}, {WINED3D_SM4_OP_MOV, WINED3DSIH_MOV, 1, 1}, {WINED3D_SM4_OP_MUL, WINED3DSIH_MUL, 1, 2}, {WINED3D_SM4_OP_RET, WINED3DSIH_RET, 0, 0}, + {WINED3D_SM4_OP_RSQ, WINED3DSIH_RSQ, 1, 1}, {WINED3D_SM4_OP_SINCOS, WINED3DSIH_SINCOS, 1, 2}, }; static const WINED3DSHADER_PARAM_REGISTER_TYPE register_type_table[] = { - /* WINED3D_SM4_RT_TEMP */ WINED3DSPR_TEMP, - /* WINED3D_SM4_RT_INPUT */ WINED3DSPR_INPUT, - /* WINED3D_SM4_RT_OUTPUT */ WINED3DSPR_OUTPUT, - /* UNKNOWN */ 0, - /* WINED3D_SM4_RT_IMMCONST */ WINED3DSPR_IMMCONST, + /* WINED3D_SM4_RT_TEMP */ WINED3DSPR_TEMP, + /* WINED3D_SM4_RT_INPUT */ WINED3DSPR_INPUT, + /* WINED3D_SM4_RT_OUTPUT */ WINED3DSPR_OUTPUT, + /* UNKNOWN */ 0, + /* WINED3D_SM4_RT_IMMCONST */ WINED3DSPR_IMMCONST, + /* UNKNOWN */ 0, + /* UNKNOWN */ 0, + /* UNKNOWN */ 0, + /* WINED3D_SM4_RT_CONSTBUFFER */ WINED3DSPR_CONSTBUFFER, }; static const struct sysval_map sysval_map[] = @@ -265,6 +285,7 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine struct wined3d_sm4_data *priv = data; DWORD token = *(*ptr)++; enum wined3d_sm4_register_type register_type; + DWORD order; register_type = (token & WINED3D_SM4_REGISTER_TYPE_MASK) >> WINED3D_SM4_REGISTER_TYPE_SHIFT; if (register_type >= sizeof(register_type_table) / sizeof(*register_type_table)) @@ -277,6 +298,16 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine src_param->reg.type = register_type_table[register_type]; } + order = (token & WINED3D_SM4_REGISTER_ORDER_MASK) >> WINED3D_SM4_REGISTER_ORDER_SHIFT; + + if (order < 1) src_param->reg.idx = ~0U; + else src_param->reg.idx = *(*ptr)++; + + if (order < 2) src_param->reg.array_idx = ~0U; + else src_param->reg.array_idx = *(*ptr)++; + + if (order > 2) FIXME("Unhandled order %u.\n", order); + if (register_type == WINED3D_SM4_RT_IMMCONST) { enum wined3d_sm4_immconst_type immconst_type = @@ -304,7 +335,6 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine } else { - src_param->reg.idx = *(*ptr)++; src_param->swizzle = (token & WINED3D_SM4_SWIZZLE_MASK) >> WINED3D_SM4_SWIZZLE_SHIFT; } @@ -319,8 +349,8 @@ static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wine { struct wined3d_sm4_data *priv = data; DWORD token = *(*ptr)++; - UINT register_idx = *(*ptr)++; enum wined3d_sm4_register_type register_type; + DWORD order; register_type = (token & WINED3D_SM4_REGISTER_TYPE_MASK) >> WINED3D_SM4_REGISTER_TYPE_SHIFT; if (register_type >= sizeof(register_type_table) / sizeof(*register_type_table)) @@ -333,7 +363,16 @@ static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wine dst_param->reg.type = register_type_table[register_type]; } - dst_param->reg.idx = register_idx; + order = (token & WINED3D_SM4_REGISTER_ORDER_MASK) >> WINED3D_SM4_REGISTER_ORDER_SHIFT; + + if (order < 1) dst_param->reg.idx = ~0U; + else dst_param->reg.idx = *(*ptr)++; + + if (order < 2) dst_param->reg.array_idx = ~0U; + else dst_param->reg.array_idx = *(*ptr)++; + + if (order > 2) FIXME("Unhandled order %u.\n", order); + dst_param->write_mask = (token & WINED3D_SM4_WRITEMASK_MASK) >> WINED3D_SM4_WRITEMASK_SHIFT; dst_param->modifiers = 0; dst_param->shift = 0; diff --git a/reactos/dll/directx/wine/wined3d/state.c b/reactos/dll/directx/wine/wined3d/state.c index ad1593c7196..2df21addfcf 100644 --- a/reactos/dll/directx/wine/wined3d/state.c +++ b/reactos/dll/directx/wine/wined3d/state.c @@ -34,11 +34,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); -#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +#define GLINFO_LOCATION (*context->gl_info) -static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); +/* GL locking for state handlers is done by the caller. */ -static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); + +static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* Used for states which are not mapped to a gl state as-is, but used somehow different, * e.g as a parameter for drawing, or which are unimplemented in windows d3d */ @@ -51,15 +54,13 @@ static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } } -static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - /* Print a WARN, this allows the stateblock code to loop over all states to generate a display - * list without causing confusing terminal output. Deliberately no special debug name here - * because its undefined. - */ - WARN("undefined state %d\n", state); +static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + ERR("Undefined state.\n"); } -static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE]; switch(Value) { @@ -80,7 +81,8 @@ static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* 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 declaration, so if it is dirty don't do anything. The @@ -102,7 +104,8 @@ static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* No z test without depth stencil buffers */ if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) { TRACE("No Z buffer - disabling depth test\n"); @@ -130,7 +133,8 @@ static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD } } -static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering * switch */ @@ -156,7 +160,8 @@ static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) { case WINED3DSHADE_FLAT: glShadeModel(GL_FLAT); @@ -174,7 +179,8 @@ static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if (stateblock->renderState[WINED3DRS_DITHERENABLE]) { glEnable(GL_DITHER); checkGLcall("glEnable GL_DITHER"); @@ -184,7 +190,8 @@ static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes, * this has to be merged with ZENABLE and ZFUNC */ @@ -197,7 +204,8 @@ static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]); if(glParm) { @@ -220,7 +228,8 @@ static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } -static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col); @@ -229,7 +238,8 @@ static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD checkGLcall("glLightModel for MODEL_AMBIENT"); } -static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ int srcBlend = GL_ZERO; int dstBlend = GL_ZERO; IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; @@ -441,11 +451,13 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } -static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n"); } -static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]); @@ -454,7 +466,8 @@ static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, W checkGLcall("glBlendColor"); } -static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ int glParm = 0; float ref; BOOL enable_ckey = FALSE; @@ -508,7 +521,7 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) { glParm = GL_NOTEQUAL; - ref = 0.0; + ref = 0.0f; } else { ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f; glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]); @@ -519,11 +532,12 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } -static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD enable = 0xFFFFFFFF; DWORD disable = 0x00000000; - if (use_vs(stateblock)) + if (!stateblock->wineD3DDevice->vs_clipping && use_vs(stateblock)) { /* 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 @@ -550,16 +564,18 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine if (stateblock->renderState[WINED3DRS_CLIPPING]) { enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]; disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]; - if(GL_SUPPORT(NV_DEPTH_CLAMP)) { - glDisable(GL_DEPTH_CLAMP_NV); - checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)"); + if (GL_SUPPORT(ARB_DEPTH_CLAMP)) + { + glDisable(GL_DEPTH_CLAMP); + checkGLcall("glDisable(GL_DEPTH_CLAMP)"); } } else { disable = 0xffffffff; enable = 0x00; - if(GL_SUPPORT(NV_DEPTH_CLAMP)) { - glEnable(GL_DEPTH_CLAMP_NV); - checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)"); + if (GL_SUPPORT(ARB_DEPTH_CLAMP)) + { + glEnable(GL_DEPTH_CLAMP); + checkGLcall("glEnable(GL_DEPTH_CLAMP)"); } } @@ -587,11 +603,13 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ WARN("Unsupported in local OpenGL implementation: glBlendEquation\n"); } -static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ int blendEquation = GL_FUNC_ADD; int blendEquationAlpha = GL_FUNC_ADD; @@ -632,8 +650,8 @@ static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD } } -static void -state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR) * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled * specular color. This is wrong: @@ -732,7 +750,8 @@ state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon checkGLcall("glMaterialfv(GL_EMISSION)"); } -static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ unsigned int i; /* Note the texture color applies to all textures whereas @@ -754,8 +773,9 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void -renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) { +static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face, + GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass) +{ glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); GL_EXTCALL(glActiveStencilFaceEXT(face)); @@ -766,8 +786,8 @@ renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLi checkGLcall("glStencilOp(...)"); } -static void -state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD onesided_enable = FALSE; DWORD twosided_enable = FALSE; GLint func = GL_ALWAYS; @@ -821,10 +841,10 @@ state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *c * 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); + renderstate_stencil_twosided(context, GL_BACK, + func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw); + renderstate_stencil_twosided(context, 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(...)"); @@ -856,7 +876,8 @@ state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *c } } -static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD mask; if(stateblock->wineD3DDevice->stencilBufferTarget) { @@ -874,7 +895,8 @@ static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock glStencilMask(mask); } -static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD mask; if(stateblock->wineD3DDevice->stencilBufferTarget) { @@ -887,7 +909,8 @@ static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, checkGLcall("glStencilMask"); } -static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); @@ -924,7 +947,8 @@ static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock } } -void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float fogstart, fogend; union { DWORD d; @@ -933,13 +957,13 @@ void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC switch(context->fog_source) { case FOGSOURCE_VS: - fogstart = 1.0; - fogend = 0.0; + fogstart = 1.0f; + fogend = 0.0f; break; case FOGSOURCE_COORD: - fogstart = 255.0; - fogend = 0.0; + fogstart = 255.0f; + fogend = 0.0f; break; case FOGSOURCE_FFP: @@ -949,8 +973,8 @@ void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC fogend = tmpvalue.f; /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/ if(fogstart == fogend) { - fogstart = -1.0 / 0.0; - fogend = 0.0; + fogstart = -1.0f / 0.0f; + fogend = 0.0f; } break; @@ -959,8 +983,8 @@ void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC * Still this is needed to make the compiler happy */ ERR("Unexpected fog coordinate source\n"); - fogstart = 0.0; - fogend = 0.0; + fogstart = 0.0f; + fogend = 0.0f; } glFogf(GL_FOG_START, fogstart); @@ -972,7 +996,8 @@ void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC TRACE("Fog End == %f\n", fogend); } -void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ enum fogsource new_source; TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); @@ -1113,13 +1138,15 @@ void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } -static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *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) { +static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) { glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)"); @@ -1129,14 +1156,16 @@ static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col); glFogfv(GL_FOG_COLOR, &col[0]); checkGLcall("glFog GL_FOG_COLOR"); } -void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1146,11 +1175,10 @@ void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)"); } -static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; GLenum Parm = 0; - const struct wined3d_stream_info_element *diffuse = &device->strided_streams.elements[WINED3D_FFP_DIFFUSE]; - BOOL isDiffuseSupplied; /* Depends on the decoded vertex declaration to read the existence of diffuse data. * The vertex declaration will call this function if the fixed function pipeline is used. @@ -1160,10 +1188,10 @@ static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine return; } - isDiffuseSupplied = diffuse->data || diffuse->buffer_object; - context->num_untracked_materials = 0; - if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) { + if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE)) + && stateblock->renderState[WINED3DRS_COLORVERTEX]) + { TRACE("diff %d, amb %d, emis %d, spec %d\n", stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE], stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE], @@ -1258,7 +1286,8 @@ static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine context->tracking_parm = Parm; } -static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; WINED3DLINEPATTERN lp; @@ -1278,7 +1307,8 @@ static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1306,7 +1336,8 @@ static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } -static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(isStateDirty(context, STATE_VDECL)) { return; } @@ -1315,8 +1346,7 @@ static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, Win * by zero and is not properly defined in opengl, so avoid it */ if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] - && (stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].data - || stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].buffer_object)) + && (stateblock->wineD3DDevice->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL))) { glEnable(GL_NORMALIZE); checkGLcall("glEnable(GL_NORMALIZE);"); @@ -1326,24 +1356,28 @@ static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; } tmpvalue; tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN]; - if(tmpvalue.f != 1.0) { + if (tmpvalue.f != 1.0f) + { FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f); } tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX]; - if(tmpvalue.f != 64.0) { + if (tmpvalue.f != 64.0f) + { FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f); } } -static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1363,7 +1397,8 @@ static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, checkGLcall("glPointParameterfEXT(...)"); } -static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1383,7 +1418,8 @@ static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, checkGLcall("glPointParameterfARB(...)"); } -static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* TODO: Group this with the viewport */ /* * POINTSCALEENABLE controls how point size value is treated. If set to @@ -1453,7 +1489,13 @@ static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3 checkGLcall("glPointSize(...);"); } -static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_debug_monitor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + WARN("token: %#x\n", stateblock->renderState[WINED3DRS_DEBUGMONITORTOKEN]); +} + +static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE]; TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", @@ -1478,7 +1520,8 @@ static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi } } -static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) { glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)"); @@ -1488,7 +1531,8 @@ static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_LASTPIXEL]) { TRACE("Last Pixel Drawing Enabled\n"); } else { @@ -1502,7 +1546,8 @@ static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ BOOL warned = FALSE; /* TODO: NV_POINT_SPRITE */ if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) { @@ -1512,7 +1557,8 @@ static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) { BOOL warned = FALSE; if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) { @@ -1530,7 +1576,8 @@ static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /** http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/ http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp @@ -1560,13 +1607,15 @@ static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } } -static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { WARN("Multisample antialiasing not supported by gl\n"); } } -static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) { glEnable(GL_MULTISAMPLE_ARB); checkGLcall("glEnable(GL_MULTISAMPLE_ARB)"); @@ -1576,7 +1625,8 @@ static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } } -static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) { glEnable(GL_SCISSOR_TEST); checkGLcall("glEnable(GL_SCISSOR_TEST)"); @@ -1586,7 +1636,8 @@ static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD } } -static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1605,7 +1656,8 @@ static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) { glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)"); @@ -1615,31 +1667,36 @@ static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA]) FIXME(" Stippled Alpha not supported yet.\n"); } -static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_ANTIALIAS]) FIXME(" Antialias not supported yet.\n"); } -static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF) FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]); } -static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE) FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]); } -static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ union { DWORD d; float f; @@ -1659,109 +1716,127 @@ static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC) FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]); } -static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR) FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]); } -static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ TRACE("Stub\n"); if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]) FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]); } -static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_WRAPU]) { FIXME("Render state WINED3DRS_WRAPU not implemented yet\n"); } } -static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_WRAPV]) { FIXME("Render state WINED3DRS_WRAPV not implemented yet\n"); } } -static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_MONOENABLE]) { FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n"); } } -static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_ROP2]) { FIXME("Render state WINED3DRS_ROP2 not implemented yet\n"); } } -static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_PLANEMASK]) { FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n"); } } -static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_SUBPIXEL]) { FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n"); } } -static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_SUBPIXELX]) { FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n"); } } -static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) { FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n"); } } -static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) { FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n"); } } -static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) { FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n"); } } -static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_ANISOTROPY]) { FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n"); } } -static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) { FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n"); } } -static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) { FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n"); } } -static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_EXTENTS]) { FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n"); } } -static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) { FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n"); } @@ -1815,7 +1890,8 @@ static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* op } /* 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) +static void set_tex_op(const struct wined3d_context *context, IWineD3DDevice *iface, + BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) { GLenum src1, src2, src3; GLenum opr1, opr2, opr3; @@ -1826,7 +1902,6 @@ static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTE 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); @@ -2840,7 +2915,8 @@ static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTE } -static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage); @@ -2891,14 +2967,15 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D if (tex_used) texture_activate_dimensions(stage, stateblock, context); } - set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, + set_tex_op(context, (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]); } -void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage); @@ -2992,12 +3069,13 @@ void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext mapped_stage, stateblock->textureState[stage][WINED3DTSS_RESULTARG]); } else { - set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, + set_tex_op(context, (IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, op, arg1, arg2, arg0); } } -static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit]; BOOL generated; @@ -3022,7 +3100,7 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W 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.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].stride + stateblock->wineD3DDevice->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)) ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format : WINED3DFMT_UNKNOWN, stateblock->wineD3DDevice->frag_pipe->ffp_proj_control); @@ -3033,8 +3111,8 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W if(generated) { FIXME("Non-power2 texture being used with generated texture coords\n"); } - /* NP2 texcoord fixup is implemented for pixelshaders (currently only in GLSL backend) so - only enable the fixed-function-pipeline fixup via pow2Matrix when no PS is used. */ + /* NP2 texcoord fixup is implemented for pixelshaders so only enable the + fixed-function-pipeline fixup via pow2Matrix when no PS is used. */ if (!use_ps(stateblock)) { TRACE("Non power two matrix multiply fixup\n"); glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix); @@ -3042,7 +3120,8 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) { +static void unloadTexCoords(const struct wined3d_context *context) +{ unsigned int texture_idx; for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) { @@ -3051,7 +3130,8 @@ static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) { } } -static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si, GLuint *curVBO) +static void loadTexCoords(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock, + const struct wined3d_stream_info *si, GLuint *curVBO) { const UINT *offset = stateblock->streamOffset; unsigned int mapped_stage = 0; @@ -3059,14 +3139,14 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) { int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX]; - const struct wined3d_stream_info_element *e; mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo]; if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue; - e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; - if (coordIdx < MAX_TEXTURES && (e->data || e->buffer_object)) + if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))) { + const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; + TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", textureNo, mapped_stage, coordIdx, e->data); @@ -3098,13 +3178,14 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined checkGLcall("loadTexCoords"); } -static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage]; - static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 }; - static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 }; - static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 }; - static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f }; + static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f }; + static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f }; if (mapped_stage == WINED3D_UNMAPPED_STAGE) { @@ -3266,12 +3347,13 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine */ GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0; - unloadTexCoords(stateblock); - loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO); + unloadTexCoords(context); + loadTexCoords(context, stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO); } } -static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them @@ -3282,14 +3364,16 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine return; } - device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock)); + device->shader_backend->shader_load_constants(context, use_ps(stateblock), use_vs(stateblock)); } -static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); - if(stateblock->pixelShader && stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) { + if (stateblock->pixelShader && stage != 0 + && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage))) + { /* The pixel shader has to know the luminance scale. Do a constants update if it * isn't scheduled anyway */ @@ -3300,7 +3384,8 @@ static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ const DWORD sampler = state - STATE_SAMPLER(0); IWineD3DBaseTexture *texture = stateblock->textures[sampler]; @@ -3308,7 +3393,7 @@ static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, W 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 + * basetexture_apply_state_changes() 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 already active because the sampler() function below, which is part of the @@ -3326,7 +3411,8 @@ static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD sampler = state - STATE_SAMPLER(0); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler]; union { @@ -3356,7 +3442,8 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler]; tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB); IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb); - IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]); + basetexture_apply_state_changes(stateblock->textures[sampler], + stateblock->textureState[sampler], stateblock->samplerState[sampler]); if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) { tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS]; @@ -3376,8 +3463,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } } - /* Trigger shader constant reloading (for NP2 texcoord fixup) - * Only do this if pshaders are used (note: fixup is currently only implemented in GLSL). */ + /* Trigger shader constant reloading (for NP2 texcoord fixup) */ if (!tex_impl->baseTexture.pow2Matrix_identity) { IWineD3DDeviceImpl* d3ddevice = stateblock->wineD3DDevice; d3ddevice->shader_backend->shader_load_np2fixup_constants( @@ -3398,7 +3484,8 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } } -void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL use_pshader = use_ps(stateblock); BOOL use_vshader = use_vs(stateblock); @@ -3435,7 +3522,7 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { - device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader); + device->shader_backend->shader_select(context, use_pshader, use_vshader); if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); @@ -3443,10 +3530,12 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } } -static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); - if(stateblock->pixelShader && stage != 0 && - ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) { + if (stateblock->pixelShader && stage != 0 + && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage))) + { /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled * anyway */ @@ -3457,7 +3546,8 @@ static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ /* This function is called by transform_view below if the view matrix was changed too * * Deliberately no check if the vertex declaration is dirty because the vdecl state @@ -3485,7 +3575,8 @@ static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, Win } } -static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ UINT index = state - STATE_CLIPPLANE(0); if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) { @@ -3493,9 +3584,20 @@ 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(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + if(!use_vs(stateblock)) { + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]); + } else { + /* with vertex shaders, clip planes are not transformed in direct3d, + * in OpenGL they are still transformed by the model view. + * Use this to swap the y coordinate if necessary + */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f); + } TRACE("Clipplane [%f,%f,%f,%f]\n", stateblock->clipplane[index][0], @@ -3508,7 +3610,8 @@ static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo glPopMatrix(); } -static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)); GLenum glMat; TRACE("Setting world matrix %d\n", matrix); @@ -3547,7 +3650,8 @@ static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ static BOOL once = FALSE; switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) { @@ -3566,7 +3670,8 @@ static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND]; switch(val) { @@ -3608,7 +3713,8 @@ static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ unsigned int k; /* If we are changing the View matrix, reset the light and clipping planes to the new view @@ -3665,7 +3771,8 @@ static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ glMatrixMode(GL_PROJECTION); checkGLcall("glMatrixMode(GL_PROJECTION)"); glLoadIdentity(); @@ -3704,7 +3811,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock * problem either. */ TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ); - if(stateblock->wineD3DDevice->render_offscreen) { + if (context->render_offscreen) + { glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ); } else { glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ); @@ -3718,7 +3826,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock * replacement shader. */ TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0); - if(stateblock->wineD3DDevice->render_offscreen) { + if (context->render_offscreen) + { glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0); } else { glOrtho(X, X + width, Y + height, Y, 0.0, -1.0); @@ -3727,12 +3836,14 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock checkGLcall("glOrtho"); /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */ - glTranslatef(0.5, 0.5, 0); - checkGLcall("glTranslatef(0.5, 0.5, 0)"); + glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f); + checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)"); + /* D3D texture coordinates are flipped compared to OpenGL ones, so * render everything upside down when rendering offscreen. */ - if (stateblock->wineD3DDevice->render_offscreen) { - glScalef(1.0, -1.0, 1.0); + if (context->render_offscreen) + { + glScalef(1.0f, -1.0f, 1.0f); checkGLcall("glScalef"); } } else { @@ -3773,16 +3884,24 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock * glScalef(1.0, flip, 2.0); */ - if (stateblock->wineD3DDevice->render_offscreen) { + /* Translate by slightly less than a half pixel to force a top-left + * filling convention. We want the difference to be large enough that + * it doesn't get lost due to rounding inside the driver, but small + * enough to prevent it from interfering with any anti-aliasing. */ + GLfloat xoffset = (63.0f / 64.0f) / stateblock->viewport.Width; + GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height; + + if (context->render_offscreen) + { /* 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); + glTranslatef(xoffset, -yoffset, -1.0f); + checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)"); + glScalef(1.0f, -1.0f, 2.0f); } 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); + glTranslatef(xoffset, yoffset, -1.0f); + checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)"); + glScalef(1.0f, 1.0f, 2.0f); } checkGLcall("glScalef"); @@ -3795,7 +3914,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock * stateblock impl is required for GL_SUPPORT * TODO: Only load / unload arrays if we have to. */ -static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) { +static inline void unloadVertexData(const struct wined3d_context *context) +{ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); @@ -3805,21 +3925,13 @@ static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) { if (GL_SUPPORT(ARB_VERTEX_BLEND)) { glDisableClientState(GL_WEIGHT_ARRAY_ARB); } - unloadTexCoords(stateblock); + unloadTexCoords(context); } -static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i) +static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context, int i) { GL_EXTCALL(glDisableVertexAttribArrayARB(i)); 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)"); context->numbered_array_mask &= ~(1 << i); } @@ -3827,7 +3939,7 @@ static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, Win /* This should match any arrays loaded in loadNumberedArrays * TODO: Only load / unload arrays if we have to. */ -static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) +static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) { /* disable any attribs (this is the same for both GLSL and ARB modes) */ GLint maxAttribs = 16; @@ -3844,7 +3956,7 @@ static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, Wine } static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, - const struct wined3d_stream_info *stream_info, WineD3DContext *context) + const struct wined3d_stream_info *stream_info, struct wined3d_context *context) { GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0; int i; @@ -4018,7 +4130,8 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, } /* Used from 2 different functions, and too big to justify making it inlined */ -static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si) +static void loadVertexData(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock, + const struct wined3d_stream_info *si) { const UINT *offset = stateblock->streamOffset; GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0; @@ -4030,11 +4143,11 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine stateblock->wineD3DDevice->instancedDraw = FALSE; /* Blend Data ---------------------------------------------- */ - e = &si->elements[WINED3D_FFP_BLENDWEIGHT]; - if (e->data || e->buffer_object - || si->elements[WINED3D_FFP_BLENDINDICES].data - || si->elements[WINED3D_FFP_BLENDINDICES].buffer_object) + if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT)) + || si->use_map & (1 << WINED3D_FFP_BLENDINDICES)) { + e = &si->elements[WINED3D_FFP_BLENDWEIGHT]; + if (GL_SUPPORT(ARB_VERTEX_BLEND)) { TRACE("Blend %d %p %d\n", e->format_desc->component_count, e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]); @@ -4061,8 +4174,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine checkGLcall("glWeightPointerARB"); - if (si->elements[WINED3D_FFP_BLENDINDICES].data - || (si->elements[WINED3D_FFP_BLENDINDICES].buffer_object)) + if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES)) { static BOOL warned; if (!warned) @@ -4086,8 +4198,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine } /* Point Size ----------------------------------------------*/ - e = &si->elements[WINED3D_FFP_PSIZE]; - if (e->data || e->buffer_object) + if (si->use_map & (1 << WINED3D_FFP_PSIZE)) { /* no such functionality in the fixed function GL pipeline */ TRACE("Cannot change ptSize here in openGl\n"); @@ -4095,11 +4206,11 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine } /* Vertex Pointers -----------------------------------------*/ - e = &si->elements[WINED3D_FFP_POSITION]; - if (e->data || e->buffer_object) + if (si->use_map & (1 << WINED3D_FFP_POSITION)) { VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data)); + e = &si->elements[WINED3D_FFP_POSITION]; if (curVBO != e->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); @@ -4129,10 +4240,11 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine } /* Normals -------------------------------------------------*/ - e = &si->elements[WINED3D_FFP_NORMAL]; - if (e->data || e->buffer_object) + if (si->use_map & (1 << WINED3D_FFP_NORMAL)) { VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data)); + + e = &si->elements[WINED3D_FFP_NORMAL]; if (curVBO != e->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); @@ -4159,11 +4271,11 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine /* NOTE: Unless we write a vertex shader to swizzle the colour*/ /* , or the user doesn't care and wants the speed advantage */ - e = &si->elements[WINED3D_FFP_DIFFUSE]; - if (e->data || e->buffer_object) + if (si->use_map & (1 << WINED3D_FFP_DIFFUSE)) { VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data)); + e = &si->elements[WINED3D_FFP_DIFFUSE]; if (curVBO != e->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); @@ -4183,22 +4295,52 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine } /* Specular Colour ------------------------------------------*/ - e = &si->elements[WINED3D_FFP_SPECULAR]; - if (e->data || e->buffer_object) + if (si->use_map & (1 << WINED3D_FFP_SPECULAR)) { TRACE("setting specular colour\n"); VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data)); + e = &si->elements[WINED3D_FFP_SPECULAR]; if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { + GLenum type = e->format_desc->gl_vtx_type; + GLint format = e->format_desc->gl_vtx_format; + if (curVBO != e->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); checkGLcall("glBindBufferARB"); curVBO = e->buffer_object; } - GL_EXTCALL(glSecondaryColorPointerEXT)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, - e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); - checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)"); + + if(format != 4 || (GLINFO_LOCATION.quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA)) + { + /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha + * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function + * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts + * 4 component secondary colors use it + */ + GL_EXTCALL(glSecondaryColorPointerEXT)(format, type, + e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + checkGLcall("glSecondaryColorPointerEXT(format, type, ...)"); + } + else + { + switch(type) + { + case GL_UNSIGNED_BYTE: + GL_EXTCALL(glSecondaryColorPointerEXT)(3, GL_UNSIGNED_BYTE, + e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)"); + break; + + default: + FIXME("Add 4 component specular color pointers for type %x\n", type); + /* Make sure that the right color component is dropped */ + GL_EXTCALL(glSecondaryColorPointerEXT)(3, type, + e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]); + checkGLcall("glSecondaryColorPointerEXT(3, type, ...)"); + } + } glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); } else { @@ -4219,7 +4361,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wine } /* Texture coords -------------------------------------------*/ - loadTexCoords(stateblock, si, &curVBO); + loadTexCoords(context, stateblock, si, &curVBO); } static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations) @@ -4245,7 +4387,8 @@ static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_i return; } -static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL fixup = FALSE; struct wined3d_stream_info *dataLocations = &device->strided_streams; @@ -4284,18 +4427,23 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo device->useDrawStridedSlow = FALSE; } } - else if (fixup || (!dataLocations->elements[WINED3D_FFP_PSIZE].data - && !dataLocations->position_transformed - && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) - || (!dataLocations->elements[WINED3D_FFP_DIFFUSE].data - && !dataLocations->elements[WINED3D_FFP_SPECULAR].data)))) + else { - /* Load the vertex data using named arrays */ - load_named = TRUE; - device->useDrawStridedSlow = FALSE; - } else { - TRACE("Not loading vertex data\n"); - device->useDrawStridedSlow = TRUE; + WORD slow_mask = (1 << WINED3D_FFP_PSIZE); + slow_mask |= -!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR)); + + if (fixup || (!dataLocations->position_transformed + && !(dataLocations->use_map & slow_mask))) + { + /* Load the vertex data using named arrays */ + load_named = TRUE; + device->useDrawStridedSlow = FALSE; + } + else + { + TRACE("Not loading vertex data\n"); + device->useDrawStridedSlow = TRUE; + } } if (context->numberedArraysLoaded && !load_numbered) @@ -4306,7 +4454,7 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo } else if (context->namedArraysLoaded) { - unloadVertexData(stateblock); + unloadVertexData(context); context->namedArraysLoaded = FALSE; } @@ -4319,12 +4467,13 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo else if (load_named) { TRACE("Loading vertex data\n"); - loadVertexData(stateblock, dataLocations); + loadVertexData(context, stateblock, dataLocations); context->namedArraysLoaded = TRUE; } } -static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ BOOL updateFog = FALSE; BOOL useVertexShaderFunction = use_vs(stateblock); BOOL usePixelShaderFunction = use_ps(stateblock); @@ -4332,6 +4481,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W /* Some stuff is in the device until we have per context tracking */ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL wasrhw = context->last_was_rhw; + unsigned int i; transformed = device->strided_streams.position_transformed; if(transformed != context->last_was_rhw && !useVertexShaderFunction) { @@ -4359,9 +4509,11 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W /* This sets the shader output position correction constants. * TODO: Move to the viewport state */ - if (useVertexShaderFunction) { - device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0; - device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height; + if (useVertexShaderFunction) + { + GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height; + device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f; + device->posFixup[3] = device->posFixup[1] * yoffset; } } @@ -4400,28 +4552,32 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W if(context->last_was_vshader) { updateFog = TRUE; - if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) { + if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) { state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context); } + for(i = 0; i < GL_LIMITS(clipplanes); i++) { + clipplane(STATE_CLIPPLANE(i), stateblock, context); + } } if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) { state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context); } } else { if(!context->last_was_vshader) { - unsigned int i; static BOOL warned = FALSE; - /* Disable all clip planes to get defined results on all drivers. See comment in the - * state_clipping state handler - */ - for(i = 0; i < GL_LIMITS(clipplanes); i++) { - glDisable(GL_CLIP_PLANE0 + i); - checkGLcall("glDisable(GL_CLIP_PLANE0 + i)"); - } + if(!device->vs_clipping) { + /* Disable all clip planes to get defined results on all drivers. See comment in the + * state_clipping state handler + */ + for(i = 0; i < GL_LIMITS(clipplanes); i++) { + glDisable(GL_CLIP_PLANE0 + i); + checkGLcall("glDisable(GL_CLIP_PLANE0 + i)"); + } - if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) { - FIXME("Clipping not supported with vertex shaders\n"); - warned = TRUE; + if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) { + FIXME("Clipping not supported with vertex shaders\n"); + warned = TRUE; + } } if(wasrhw) { /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex @@ -4437,6 +4593,14 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } updateFog = TRUE; + + /* Vertex shader clipping ignores the view matrix. Update all clipplanes + * (Note: ARB shaders can read the clip planes for clipping emulation even if + * device->vs_clipping is false. + */ + for(i = 0; i < GL_LIMITS(clipplanes); i++) { + clipplane(STATE_CLIPPLANE(i), stateblock, context); + } } } @@ -4444,7 +4608,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W * application */ if (!isStateDirty(context, STATE_PIXELSHADER)) { - device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction); + device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction); if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) { shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); @@ -4466,7 +4630,8 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W } } -static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ UINT width, height; IWineD3DSurfaceImpl *target; @@ -4474,13 +4639,14 @@ static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, W checkGLcall("glDepthRange"); /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering */ - if(stateblock->wineD3DDevice->render_offscreen) { + if (context->render_offscreen) + { glViewport(stateblock->viewport.X, stateblock->viewport.Y, stateblock->viewport.Width, stateblock->viewport.Height); } else { target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; - target->get_drawable_size(target, &width, &height); + target->get_drawable_size(context, &width, &height); glViewport(stateblock->viewport.X, (height - (stateblock->viewport.Y + stateblock->viewport.Height)), @@ -4490,9 +4656,13 @@ static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, W 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] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height; +static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height; + + stateblock->wineD3DDevice->posFixup[2] = (63.0f / 64.0f) / stateblock->viewport.Width; + stateblock->wineD3DDevice->posFixup[3] = stateblock->wineD3DDevice->posFixup[1] * yoffset; + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) { transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); } @@ -4501,7 +4671,8 @@ static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, } } -static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ UINT Index = state - STATE_ACTIVELIGHT(0); const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index]; @@ -4510,7 +4681,7 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex checkGLcall("glDisable(GL_LIGHT0 + Index)"); } else { float quad_att; - float colRGBA[] = {0.0, 0.0, 0.0, 0.0}; + float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/ glMatrixMode(GL_MODELVIEW); @@ -4542,9 +4713,9 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex checkGLcall("glLightfv"); if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) { - quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range); + quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range); } else { - quad_att = 0; /* 0 or MAX? (0 seems to be ok) */ + quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */ } /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk, @@ -4616,20 +4787,22 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex return; } -static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ RECT *pRect = &stateblock->scissorRect; UINT height; UINT width; IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0]; - target->get_drawable_size(target, &width, &height); + target->get_drawable_size(context, &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 */ 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) { + if (context->render_offscreen) + { glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } else { glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); @@ -4637,7 +4810,8 @@ static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D checkGLcall("glScissor"); } -static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) { GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); } else { @@ -4646,8 +4820,10 @@ static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } } -static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - if(stateblock->wineD3DDevice->render_offscreen) { +static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ + if (context->render_offscreen) + { glFrontFace(GL_CCW); checkGLcall("glFrontFace(GL_CCW)"); } else { @@ -4657,689 +4833,692 @@ static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo } 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 }, + { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE }, + { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE }, + { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE }, + { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE }, /* 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 }, + { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, - { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 }, + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE }, { 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_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_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_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE }, - { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 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_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX }, - { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 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_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_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 }, + { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, /* 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 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; 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 }, + { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, + { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, + { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE }, /* 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 }, + { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE }, /* 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 }, + { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE }, /* Viewport */ - { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 }, + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE }, /* 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 }, + { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, /* Fog */ - { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_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_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_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_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSIZE_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_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, - { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 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_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, - { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported, * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states. * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix */ { 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(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, { 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 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; 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_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_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_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_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_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_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_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_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_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 }, - { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 }, - { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 }, - { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 }, - { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 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 }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, }; #undef GLINFO_LOCATION #define GLINFO_LOCATION (*gl_info) +/* Context activation is done by the caller. */ static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { } -static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) +static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, + const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps) { pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD | WINED3DTEXOPCAPS_ADDSIGNED | @@ -5414,19 +5593,21 @@ static unsigned int num_handlers(const APPLYSTATEFUNC *funcs) return i; } -static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *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) { +static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *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); } HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, - const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex, + const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex, const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) { unsigned int i, type, handlers; @@ -5468,7 +5649,7 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_ */ if(set[cur[i].state]) continue; /* Skip state lines depending on unsupported extensions */ - if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue; + if (!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 diff --git a/reactos/dll/directx/wine/wined3d/stateblock.c b/reactos/dll/directx/wine/wined3d/stateblock.c index 1c9b5a8db9f..239b777cef6 100644 --- a/reactos/dll/directx/wine/wined3d/stateblock.c +++ b/reactos/dll/directx/wine/wined3d/stateblock.c @@ -31,11 +31,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); * Stateblock helper functions follow **************************************/ -/** Allocates the correct amount of space for pixel and vertex shader constants, +/* Allocates the correct amount of space for pixel and vertex shader constants, * along with their set/changed flags on the given stateblock object */ -HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) { - +HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) +{ IWineD3DStateBlockImpl *This = object; /* Allocate space for floating point constants */ @@ -113,11 +113,8 @@ static inline void stateblock_set_bits(DWORD *map, UINT map_size) } /** Set all members of a stateblock savedstate to the given value */ -void stateblock_savedstates_set( - IWineD3DStateBlock* iface, - SAVEDSTATES* states, - BOOL value) { - +void stateblock_savedstates_set(IWineD3DStateBlock *iface, SAVEDSTATES *states, BOOL value) +{ IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; unsigned bsize = sizeof(BOOL); @@ -228,7 +225,7 @@ void stateblock_copy( memcpy(Dest->vertexShaderConstantI, This->vertexShaderConstantI, sizeof(INT) * MAX_CONST_I * 4); memcpy(Dest->pixelShaderConstantB, This->pixelShaderConstantB, sizeof(BOOL) * MAX_CONST_B); memcpy(Dest->pixelShaderConstantI, This->pixelShaderConstantI, sizeof(INT) * MAX_CONST_I * 4); - + memcpy(Dest->streamStride, This->streamStride, sizeof(UINT) * MAX_STREAMS); memcpy(Dest->streamOffset, This->streamOffset, sizeof(UINT) * MAX_STREAMS); memcpy(Dest->streamSource, This->streamSource, sizeof(IWineD3DBuffer *) * MAX_STREAMS); @@ -357,7 +354,7 @@ static inline void record_lights(IWineD3DStateBlockImpl *This, IWineD3DStateBloc LIST_FOR_EACH(e, &This->lightMap[i]) { BOOL updated = FALSE; PLIGHTINFOEL *src = LIST_ENTRY(e, PLIGHTINFOEL, entry), *realLight; - if(!src->changed || !src->enabledChanged) continue; + if (!src->changed && !src->enabledChanged) continue; /* Look up the light in the destination */ LIST_FOR_EACH(f, &targetStateBlock->lightMap[i]) { @@ -1087,9 +1084,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat 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 @@ -1292,28 +1286,27 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat This->textures[i] = NULL; } - /* 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) { WINED3DVIEWPORT vp; hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer); - if( hr == WINED3D_OK && backbuffer != NULL) { + if (SUCCEEDED(hr) && backbuffer) + { + WINED3DSURFACE_DESC desc; + RECT scissorrect; + IWineD3DSurface_GetDesc(backbuffer, &desc); IWineD3DSurface_Release(backbuffer); + /* Set the default scissor rect values */ scissorrect.left = 0; - scissorrect.right = width; + scissorrect.right = desc.width; scissorrect.top = 0; - scissorrect.bottom = height; + scissorrect.bottom = desc.height; hr = IWineD3DDevice_SetScissorRect(device, &scissorrect); - if( hr != WINED3D_OK ) { - ERR("This should never happen, expect rendering issues!\n"); - } + if (FAILED(hr)) ERR("This should never happen, expect rendering issues!\n"); } /* Set the default viewport */ diff --git a/reactos/dll/directx/wine/wined3d/surface.c b/reactos/dll/directx/wine/wined3d/surface.c index 9e9d55c5b33..cce613c6657 100644 --- a/reactos/dll/directx/wine/wined3d/surface.c +++ b/reactos/dll/directx/wine/wined3d/surface.c @@ -32,13 +32,214 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); WINE_DECLARE_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info -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 void surface_remove_pbo(IWineD3DSurfaceImpl *This); +#define GLINFO_LOCATION (*gl_info) -void surface_force_reload(IWineD3DSurface *iface) +static void surface_cleanup(IWineD3DSurfaceImpl *This) +{ + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + 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. When destroying the primary render + * target, Uninit3D() will activate a context before doing anything. */ + if (device->render_targets && device->render_targets[0]) + { + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + } + + ENTER_GL(); + + if (This->texture_name) + { + /* Release the OpenGL texture. */ + TRACE("Deleting texture %u.\n", This->texture_name); + glDeleteTextures(1, &This->texture_name); + } + + if (This->Flags & SFLAG_PBO) + { + /* Delete the PBO. */ + 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); + DeleteDC(This->hDC); + /* Release the DIB section. */ + DeleteObject(This->dib.DIBsection); + This->dib.bitmap_data = NULL; + This->resource.allocatedMemory = NULL; + } + + if (This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem((IWineD3DSurface *)This, NULL); + if (This->overlay_dest) list_remove(&This->overlay_entry); + + HeapFree(GetProcessHeap(), 0, This->palette9); + + resource_cleanup((IWineD3DResource *)This); +} + +UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height) +{ + UINT size; + + if (format_desc->format == WINED3DFMT_UNKNOWN) + { + size = 0; + } + else if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + UINT row_block_count = (width + format_desc->block_width - 1) / format_desc->block_width; + UINT row_count = (height + format_desc->block_height - 1) / format_desc->block_height; + size = row_count * row_block_count * format_desc->block_byte_count; + } + else + { + /* The pitch is a multiple of 4 bytes. */ + size = height * (((width * format_desc->byte_count) + alignment - 1) & ~(alignment - 1)); + } + + if (format_desc->heightscale != 0.0f) size *= format_desc->heightscale; + + return size; +} + +HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, + UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, + UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, + WINED3DPOOL pool, IUnknown *parent) +{ + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &GLINFO_LOCATION); + void (*cleanup)(IWineD3DSurfaceImpl *This); + unsigned int resource_size; + HRESULT hr; + + if (multisample_quality > 0) + { + FIXME("multisample_quality set to %u, substituting 0\n", multisample_quality); + multisample_quality = 0; + } + + /* FIXME: Check that the format is supported by the device. */ + + resource_size = surface_calculate_size(format_desc, alignment, width, height); + + /* Look at the implementation and set the correct Vtable. */ + switch (surface_type) + { + case SURFACE_OPENGL: + surface->lpVtbl = &IWineD3DSurface_Vtbl; + cleanup = surface_cleanup; + break; + + case SURFACE_GDI: + surface->lpVtbl = &IWineGDISurface_Vtbl; + cleanup = surface_gdi_cleanup; + break; + + default: + ERR("Requested unknown surface implementation %#x.\n", surface_type); + return WINED3DERR_INVALIDCALL; + } + + hr = resource_init((IWineD3DResource *)surface, WINED3DRTYPE_SURFACE, + device, resource_size, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x.\n", hr); + return hr; + } + + /* "Standalone" surface. */ + IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL); + + surface->currentDesc.Width = width; + surface->currentDesc.Height = height; + surface->currentDesc.MultiSampleType = multisample_type; + surface->currentDesc.MultiSampleQuality = multisample_quality; + surface->texture_level = level; + list_init(&surface->overlays); + + /* Flags */ + surface->Flags = SFLAG_NORMCOORD; /* Default to normalized coords. */ + if (discard) surface->Flags |= SFLAG_DISCARD; + if (lockable || format == WINED3DFMT_D16_LOCKABLE) surface->Flags |= SFLAG_LOCKABLE; + + /* Quick lockable sanity check. + * TODO: remove this after surfaces, usage and lockability have been debugged properly + * this function is too deep to need to care about things like this. + * Levels need to be checked too, since they all affect what can be done. */ + switch (pool) + { + case WINED3DPOOL_SCRATCH: + if(!lockable) + { + FIXME("Called with a pool of SCRATCH and a lockable of FALSE " + "which are mutually exclusive, setting lockable to TRUE.\n"); + lockable = TRUE; + } + break; + + case WINED3DPOOL_SYSTEMMEM: + if (!lockable) + FIXME("Called with a pool of SYSTEMMEM and a lockable of FALSE, this is acceptable but unexpected.\n"); + break; + + case WINED3DPOOL_MANAGED: + if (usage & WINED3DUSAGE_DYNAMIC) + FIXME("Called with a pool of MANAGED and a usage of DYNAMIC which are mutually exclusive.\n"); + break; + + case WINED3DPOOL_DEFAULT: + if (lockable && !(usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) + WARN("Creating a lockable surface with a POOL of DEFAULT, that doesn't specify DYNAMIC usage.\n"); + break; + + default: + FIXME("Unknown pool %#x.\n", pool); + break; + }; + + if (usage & WINED3DUSAGE_RENDERTARGET && pool != WINED3DPOOL_DEFAULT) + { + FIXME("Trying to create a render target that isn't in the default pool.\n"); + } + + /* Mark the texture as dirty so that it gets loaded first time around. */ + surface_add_dirty_rect((IWineD3DSurface *)surface, NULL); + list_init(&surface->renderbuffers); + + TRACE("surface %p, memory %p, size %u\n", surface, surface->resource.allocatedMemory, surface->resource.size); + + /* Call the private setup routine */ + hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)surface); + if (FAILED(hr)) + { + ERR("Private setup failed, returning %#x\n", hr); + cleanup(surface); + return hr; + } + + return hr; +} + +static void surface_force_reload(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; @@ -53,12 +254,12 @@ void surface_set_texture_name(IWineD3DSurface *iface, GLuint new_name, BOOL srgb if(srgb) { - name = &This->glDescription.srgbTextureName; + name = &This->texture_name_srgb; flag = SFLAG_INSRGBTEX; } else { - name = &This->glDescription.textureName; + name = &This->texture_name; flag = SFLAG_INTEXTURE; } @@ -83,23 +284,24 @@ void surface_set_texture_target(IWineD3DSurface *iface, GLenum target) TRACE("(%p) : setting target %#x\n", This, target); - if (This->glDescription.target != target) + if (This->texture_target != target) { if (target == GL_TEXTURE_RECTANGLE_ARB) { This->Flags &= ~SFLAG_NORMCOORD; } - else if (This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) + else if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) { This->Flags |= SFLAG_NORMCOORD; } } - This->glDescription.target = target; + This->texture_target = target; surface_force_reload(iface); } +/* Context activation is done by the caller. */ static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This, BOOL srgb) { - int active_sampler; + DWORD 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 @@ -118,7 +320,8 @@ static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This, BOOL srgb) { LEAVE_GL(); active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB]; - if (active_sampler != -1) { + if (active_sampler != WINED3D_UNMAPPED_STAGE) + { IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler)); } IWineD3DSurface_BindTexture((IWineD3DSurface *)This, srgb); @@ -136,8 +339,13 @@ static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device) return FALSE; } -/* This call just downloads data, the caller is responsible for activating the - * right context and binding the correct texture. */ +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + +/* This call just downloads data, the caller is responsible for binding the + * correct texture. */ +/* Context activation is done by the caller. */ static void surface_download_data(IWineD3DSurfaceImpl *This) { const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; @@ -150,29 +358,28 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { ENTER_GL(); - if (format_desc->format == WINED3DFMT_DXT1 || format_desc->format == WINED3DFMT_DXT2 - || format_desc->format == WINED3DFMT_DXT3 || format_desc->format == WINED3DFMT_DXT4 - || format_desc->format == WINED3DFMT_DXT5 || format_desc->format == WINED3DFMT_ATI2N) + if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) { - 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 { - TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", - This, This->glDescription.level, format_desc->glFormat, format_desc->glType, - This->resource.allocatedMemory); + TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p.\n", + This, This->texture_level, format_desc->glFormat, format_desc->glType, + This->resource.allocatedMemory); - if(This->Flags & SFLAG_PBO) { - GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo)); - checkGLcall("glBindBufferARB"); - GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, NULL)); - checkGLcall("glGetCompressedTexImageARB()"); - GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); - checkGLcall("glBindBufferARB"); - } else { - GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory)); - checkGLcall("glGetCompressedTexImageARB()"); - } + if (This->Flags & SFLAG_PBO) + { + GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo)); + checkGLcall("glBindBufferARB"); + GL_EXTCALL(glGetCompressedTexImageARB(This->texture_target, This->texture_level, NULL)); + checkGLcall("glGetCompressedTexImageARB"); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); + checkGLcall("glBindBufferARB"); } + else + { + GL_EXTCALL(glGetCompressedTexImageARB(This->texture_target, + This->texture_level, This->resource.allocatedMemory)); + checkGLcall("glGetCompressedTexImageARB"); + } + LEAVE_GL(); } else { void *mem; @@ -198,23 +405,21 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { mem = This->resource.allocatedMemory; } - TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level, - format, type, mem); + TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", + This, This->texture_level, 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, format, - type, NULL); - checkGLcall("glGetTexImage()"); + glGetTexImage(This->texture_target, This->texture_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, format, - type, mem); - checkGLcall("glGetTexImage()"); + glGetTexImage(This->texture_target, This->texture_level, format, type, mem); + checkGLcall("glGetTexImage"); } LEAVE_GL(); @@ -290,105 +495,70 @@ 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. */ +/* This call just uploads data, the caller is responsible for binding the + * correct texture. */ +/* Context activation is done by the caller. */ static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) { const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; - if (format_desc->heightscale != 1.0 && format_desc->heightscale != 0.0) height *= format_desc->heightscale; + TRACE("This %p, internal %#x, width %d, height %d, format %#x, type %#x, data %p.\n", + This, internal, width, height, format, type, data); + TRACE("target %#x, level %u, resource size %u.\n", + This->texture_target, This->texture_level, This->resource.size); - if (format_desc->format == WINED3DFMT_DXT1 || format_desc->format == WINED3DFMT_DXT2 - || format_desc->format == WINED3DFMT_DXT3 || format_desc->format == WINED3DFMT_DXT4 - || format_desc->format == WINED3DFMT_DXT5 || format_desc->format == WINED3DFMT_ATI2N) + if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale; + + ENTER_GL(); + + if (This->Flags & SFLAG_PBO) { - if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { - FIXME("Using DXT1/3/5 without advertized support\n"); - } else { - /* glCompressedTexSubImage2D for uploading and glTexImage2D for allocating does not work well on some drivers(r200 dri, MacOS ATI driver) - * glCompressedTexImage2D does not accept NULL pointers. So for compressed textures surface_allocate_surface does nothing, and this - * function uses glCompressedTexImage2D instead of the SubImage call - */ - TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data); - ENTER_GL(); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); + checkGLcall("glBindBufferARB"); - if(This->Flags & SFLAG_PBO) { - GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); - checkGLcall("glBindBufferARB"); - TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data); - - GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal, - width, height, 0 /* border */, This->resource.size, NULL)); - checkGLcall("glCompressedTexSubImage2D"); - - GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); - checkGLcall("glBindBufferARB"); - } else { - GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal, - width, height, 0 /* border */, This->resource.size, data)); - checkGLcall("glCompressedTexSubImage2D"); - } - LEAVE_GL(); - } - } else { - TRACE("(%p) : Calling glTexSubImage2D w %d, h %d, data, %p\n", This, width, height, data); - ENTER_GL(); - - if(This->Flags & SFLAG_PBO) { - GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); - checkGLcall("glBindBufferARB"); - TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data); - - glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, NULL); - checkGLcall("glTexSubImage2D"); - - GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); - checkGLcall("glBindBufferARB"); - } - else { - glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data); - checkGLcall("glTexSubImage2D"); - } - - LEAVE_GL(); + TRACE("(%p) pbo: %#x, data: %p.\n", This, This->pbo, data); + data = NULL; } + + if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + TRACE("Calling glCompressedTexSubImage2DARB.\n"); + + GL_EXTCALL(glCompressedTexSubImage2DARB(This->texture_target, This->texture_level, + 0, 0, width, height, internal, This->resource.size, data)); + checkGLcall("glCompressedTexSubImage2DARB"); + } + else + { + TRACE("Calling glTexSubImage2D.\n"); + + glTexSubImage2D(This->texture_target, This->texture_level, + 0, 0, width, height, format, type, data); + checkGLcall("glTexSubImage2D"); + } + + if (This->Flags & SFLAG_PBO) + { + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("glBindBufferARB"); + } + + LEAVE_GL(); } -/* This call just allocates the texture, the caller is responsible for - * activating the right context and binding the correct texture. */ +/* This call just allocates the texture, the caller is responsible for binding + * the correct texture. */ +/* Context activation is done by the caller. */ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) { const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; BOOL enable_client_storage = FALSE; const BYTE *mem = NULL; - if (format_desc->heightscale != 1.0 && format_desc->heightscale != 0.0) height *= format_desc->heightscale; + if (format_desc->heightscale != 1.0f && format_desc->heightscale != 0.0f) height *= format_desc->heightscale; TRACE("(%p) : Creating surface (target %#x) level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", - This, This->glDescription.target, This->glDescription.level, debug_d3dformat(format_desc->format), + This, This->texture_target, This->texture_level, debug_d3dformat(format_desc->format), internal, width, height, format, type); - if (format_desc->format == WINED3DFMT_DXT1 || format_desc->format == WINED3DFMT_DXT2 - || format_desc->format == WINED3DFMT_DXT3 || format_desc->format == WINED3DFMT_DXT4 - || format_desc->format == WINED3DFMT_DXT5 || format_desc->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"); - - /* We have to point GL to the client storage memory here, because upload_data might use a PBO. This means a double upload - * once, unfortunately - */ - if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { - /* 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; - } - ENTER_GL(); if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) { @@ -413,8 +583,18 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); } } - glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, mem); - checkGLcall("glTexImage2D"); + + if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED && mem) + { + GL_EXTCALL(glCompressedTexImage2DARB(This->texture_target, This->texture_level, + internal, width, height, 0, This->resource.size, mem)); + } + else + { + glTexImage2D(This->texture_target, This->texture_level, + internal, width, height, 0, format, type, mem); + checkGLcall("glTexImage2D"); + } if(enable_client_storage) { glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); @@ -426,6 +606,7 @@ static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, /* In D3D the depth stencil dimensions have to be greater than or equal to the * render target dimensions. With FBOs, the dimensions have to be an exact match. */ /* TODO: We should synchronize the renderbuffer's content with the texture's content. */ +/* GL locking is done by the caller */ void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; renderbuffer_entry_t *entry; @@ -526,64 +707,31 @@ void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect) } } +static inline BOOL surface_can_stretch_rect(IWineD3DSurfaceImpl *src, IWineD3DSurfaceImpl *dst) +{ + return ((src->resource.format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) + || (src->resource.usage & WINED3DUSAGE_RENDERTARGET)) + && ((dst->resource.format_desc->Flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) + || (dst->resource.usage & WINED3DUSAGE_RENDERTARGET)) + && (src->resource.format_desc->format == dst->resource.format_desc->format + || (is_identity_fixup(src->resource.format_desc->color_fixup) + && is_identity_fixup(dst->resource.format_desc->color_fixup))); +} + static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); - if (ref == 0) { - 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); - } + if (!ref) + { + surface_cleanup(This); - ENTER_GL(); - if (This->glDescription.textureName != 0) { /* release the openGL texture.. */ - TRACE("Deleting texture %d\n", This->glDescription.textureName); - glDeleteTextures(1, &This->glDescription.textureName); - } - - if(This->Flags & SFLAG_PBO) { - /* Delete the PBO */ - 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); - DeleteDC(This->hDC); - /* Release the DIB section */ - DeleteObject(This->dib.DIBsection); - This->dib.bitmap_data = NULL; - This->resource.allocatedMemory = NULL; - } - if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL); - - HeapFree(GetProcessHeap(), 0, This->palette9); - - resource_cleanup((IWineD3DResource *)iface); - - if(This->overlay_dest) { - list_remove(&This->overlay_entry); - } - - TRACE("(%p) Released\n", This); + TRACE("(%p) Released.\n", This); HeapFree(GetProcessHeap(), 0, This); - } + return ref; } @@ -602,13 +750,13 @@ void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) { IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) baseTexture; TRACE("Passing to container\n"); - tex_impl->baseTexture.internal_preload(baseTexture, SRGB_RGB); + tex_impl->baseTexture.internal_preload(baseTexture, srgb); IWineD3DBaseTexture_Release(baseTexture); } else { TRACE("(%p) : About to load surface\n", This); if(!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); } if (This->resource.format_desc->format == WINED3DFMT_P8 @@ -630,7 +778,7 @@ void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) GLclampf tmp; tmp = 0.9f; ENTER_GL(); - glPrioritizeTextures(1, &This->glDescription.textureName, &tmp); + glPrioritizeTextures(1, &This->texture_name, &tmp); LEAVE_GL(); } } @@ -641,6 +789,7 @@ static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { surface_internal_preload(iface, SRGB_ANY); } +/* Context activation is done by the caller. */ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT); This->resource.allocatedMemory = @@ -648,11 +797,11 @@ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); - checkGLcall("glBindBuffer(GL_PIXEL_UNPACK_BUFFER, This->pbo)"); + checkGLcall("glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, This->pbo)"); GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory)); - checkGLcall("glGetBufferSubData"); + checkGLcall("glGetBufferSubDataARB"); GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo)); - checkGLcall("glDeleteBuffers"); + checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); This->pbo = 0; @@ -662,6 +811,7 @@ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; renderbuffer_entry_t *entry, *entry2; TRACE("(%p)\n", iface); @@ -689,8 +839,11 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); } IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSRGBTEX, FALSE); This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + /* Destroy PBOs, but load them into real sysmem before */ if(This->Flags & SFLAG_PBO) { surface_remove_pbo(This); @@ -716,8 +869,10 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **) &texture); if(!texture) { ENTER_GL(); - glDeleteTextures(1, &This->glDescription.textureName); - This->glDescription.textureName = 0; + glDeleteTextures(1, &This->texture_name); + This->texture_name = 0; + glDeleteTextures(1, &This->texture_name_srgb); + This->texture_name_srgb = 0; LEAVE_GL(); } else { IWineD3DBaseTexture_Release(texture); @@ -729,13 +884,6 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DSurface IWineD3DSurface parts follow ****************************************************** */ -static void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - TRACE("(%p) : returning %p\n", This, &This->glDescription); - *glDescription = &This->glDescription; -} - /* Read the framebuffer back into the surface */ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) { IWineD3DSwapChainImpl *swapchain; @@ -854,11 +1002,11 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v /* Save old pixel store pack state */ glGetIntegerv(GL_PACK_ROW_LENGTH, &rowLen); - checkGLcall("glIntegerv"); + checkGLcall("glGetIntegerv"); glGetIntegerv(GL_PACK_SKIP_PIXELS, &skipPix); - checkGLcall("glIntegerv"); + checkGLcall("glGetIntegerv"); glGetIntegerv(GL_PACK_SKIP_ROWS, &skipRow); - checkGLcall("glIntegerv"); + checkGLcall("glGetIntegerv"); /* Setup pixel store pack state -- to glReadPixels into the correct place */ glPixelStorei(GL_PACK_ROW_LENGTH, This->currentDesc.Width); @@ -1039,18 +1187,15 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) * 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); + glCopyTexSubImage2D(This->texture_target, This->texture_level, + 0, 0, 0, 0, This->currentDesc.Width, This->currentDesc.Height); checkGLcall("glCopyTexSubImage2D"); glReadBuffer(prevRead); checkGLcall("glReadBuffer"); LEAVE_GL(); - TRACE("Updated target %d\n", This->glDescription.target); + TRACE("Updated target %d\n", This->texture_target); } static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { @@ -1074,7 +1219,7 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { GLenum error; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glGenBuffersARB(1, &This->pbo)); @@ -1120,6 +1265,7 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; + const RECT *pass_rect = pRect; TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory); @@ -1152,77 +1298,24 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED goto lock_end; } - /* 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 - */ - if ((This->Flags & SFLAG_SWAPCHAIN) || iface == myDevice->render_targets[0]) + /* IWineD3DSurface_LoadLocation() does not check if the rectangle specifies + * the full surface. Most callers don't need that, so do it here. */ + if (pRect && pRect->top == 0 && pRect->left == 0 + && pRect->right == This->currentDesc.Width + && pRect->bottom == This->currentDesc.Height) { - const RECT *pass_rect = pRect; + pass_rect = NULL; + } - /* IWineD3DSurface_LoadLocation does not check if the rectangle specifies the full surfaces - * because most caller functions do not need that. So do that here - */ - if(pRect && - pRect->top == 0 && - pRect->left == 0 && - pRect->right == This->currentDesc.Width && - pRect->bottom == This->currentDesc.Height) { - pass_rect = NULL; - } - - switch(wined3d_settings.rendertargetlock_mode) { - case RTL_TEXDRAW: - case RTL_TEXTEX: - FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n"); -#if 0 - /* Disabled for now. LoadLocation prefers the texture over the drawable as the source. So if we copy to the - * texture first, then to sysmem, we'll avoid glReadPixels and use glCopyTexImage and glGetTexImage2D instead. - * This may be faster on some cards - */ - IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* No partial texture copy yet */); -#endif - /* drop through */ - - case RTL_AUTO: - case RTL_READDRAW: - case RTL_READTEX: - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pass_rect); - break; - - case RTL_DISABLE: - break; - } - } else if(iface == myDevice->stencilBufferTarget) { - /** the depth stencil in openGL has a format of GL_FLOAT - * which should be good for WINED3DFMT_D16_LOCKABLE - * and WINED3DFMT_D16 - * it is unclear what format the stencil buffer is in except. - * 'Each index is converted to fixed point... - * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their - * mappings in the table GL_PIXEL_MAP_S_TO_S. - * glReadPixels(This->lockedRect.left, - * This->lockedRect.bottom - j - 1, - * This->lockedRect.right - This->lockedRect.left, - * 1, - * GL_DEPTH_COMPONENT, - * type, - * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top))); - * - * Depth Stencil surfaces which are not the current depth stencil target should have their data in a - * gl texture(next path), or in local memory(early return because of set SFLAG_INSYSMEM above). If - * none of that is the case the problem is not in this function :-) - ********************************************/ - FIXME("Depth stencil locking not supported yet\n"); - } else { - /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */ - TRACE("locking an ordinary surface\n"); - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */); + if (!(wined3d_settings.rendertargetlock_mode == RTL_DISABLE + && ((This->Flags & SFLAG_SWAPCHAIN) || iface == myDevice->render_targets[0]))) + { + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pass_rect); } lock_end: if(This->Flags & SFLAG_PBO) { - ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(myDevice, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); @@ -1292,10 +1385,10 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm } glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store); - checkGLcall("glIntegerv"); + checkGLcall("glGetIntegerv"); glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]); - checkGLcall("glIntegerv"); - glPixelZoom(1.0, -1.0); + checkGLcall("glGetIntegerv"); + glPixelZoom(1.0f, -1.0f); checkGLcall("glPixelZoom"); /* If not fullscreen, we need to skip a number of bytes to find the next row of data */ @@ -1303,7 +1396,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width); glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1); - checkGLcall("glRasterPos2f"); + checkGLcall("glRasterPos3i"); /* Some drivers(radeon dri, others?) don't like exceptions during * glDrawPixels. If the surface is a DIB section, it might be in GDIMode @@ -1345,7 +1438,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm checkGLcall("glBindBufferARB"); } - glPixelZoom(1.0,1.0); + glPixelZoom(1.0f, 1.0f); checkGLcall("glPixelZoom"); glRasterPos3iv(&prev_rasterpos[0]); @@ -1353,7 +1446,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm /* Reset to previous pack row length */ glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes); - checkGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH"); + checkGLcall("glPixelStorei(GL_UNPACK_ROW_LENGTH)"); if(!swapchain) { glDrawBuffer(myDevice->offscreenBuffer); @@ -1382,7 +1475,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { if (This->Flags & SFLAG_PBO) { TRACE("Freeing PBO memory\n"); - ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(myDevice, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); @@ -1423,14 +1516,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { switch(wined3d_settings.rendertargetlock_mode) { case RTL_READTEX: - case RTL_TEXTEX: - ActivateContext(myDevice, iface, CTXUSAGE_BLIT); IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */); /* drop through */ - case RTL_AUTO: case RTL_READDRAW: - case RTL_TEXDRAW: IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, fullsurface ? NULL : &This->dirtyRect); break; } @@ -1662,7 +1751,6 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ } 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; } @@ -1684,7 +1772,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ if (colorkey_active) { *convert = CONVERT_CK_565; *format = GL_RGBA; - *internal = GL_RGBA; + *internal = GL_RGB5_A1; *type = GL_UNSIGNED_SHORT_5_5_5_1; } break; @@ -1693,7 +1781,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ if (colorkey_active) { *convert = CONVERT_CK_5551; *format = GL_BGRA; - *internal = GL_RGBA; + *internal = GL_RGB5_A1; *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; } break; @@ -1702,7 +1790,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ if (colorkey_active) { *convert = CONVERT_CK_RGB24; *format = GL_RGBA; - *internal = GL_RGBA; + *internal = GL_RGBA8; *type = GL_UNSIGNED_INT_8_8_8_8; *target_bpp = 4; } @@ -1712,16 +1800,15 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ if (colorkey_active) { *convert = CONVERT_RGB32_888; *format = GL_RGBA; - *internal = GL_RGBA; + *internal = GL_RGBA8; *type = GL_UNSIGNED_INT_8_8_8_8; } break; case WINED3DFMT_R8G8_SNORM: - if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break; + if (GL_SUPPORT(NV_TEXTURE_SHADER)) break; *convert = CONVERT_V8U8; *format = GL_BGR; - *internal = GL_RGB8; *type = GL_UNSIGNED_BYTE; *target_bpp = 3; break; @@ -1735,7 +1822,6 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */ *target_bpp = 2; *format = GL_RGB; - *internal = GL_RGB5; *type = GL_UNSIGNED_SHORT_5_6_5; } break; @@ -1752,25 +1838,22 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ */ } else { *format = GL_BGRA; - *internal = GL_RGB8; *type = GL_UNSIGNED_INT_8_8_8_8_REV; } break; case WINED3DFMT_R8G8B8A8_SNORM: - if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break; + if (GL_SUPPORT(NV_TEXTURE_SHADER)) break; *convert = CONVERT_Q8W8V8U8; *format = GL_BGRA; - *internal = GL_RGBA8; *type = GL_UNSIGNED_BYTE; *target_bpp = 4; break; case WINED3DFMT_R16G16_SNORM: - if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break; + if (GL_SUPPORT(NV_TEXTURE_SHADER)) break; *convert = CONVERT_V16U16; *format = GL_BGR; - *internal = GL_RGB16_EXT; *type = GL_UNSIGNED_SHORT; *target_bpp = 6; break; @@ -1782,7 +1865,6 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ */ *convert = CONVERT_A4L4; *format = GL_LUMINANCE_ALPHA; - *internal = GL_LUMINANCE4_ALPHA4; *type = GL_UNSIGNED_BYTE; *target_bpp = 2; break; @@ -1790,7 +1872,6 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ case WINED3DFMT_R16G16_UNORM: *convert = CONVERT_G16R16; *format = GL_RGB; - *internal = GL_RGB16_EXT; *type = GL_UNSIGNED_SHORT; *target_bpp = 6; break; @@ -1798,7 +1879,6 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ case WINED3DFMT_R16G16_FLOAT: *convert = CONVERT_R16G16F; *format = GL_RGB; - *internal = GL_RGB16F_ARB; *type = GL_HALF_FLOAT_ARB; *target_bpp = 6; break; @@ -1806,11 +1886,33 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ case WINED3DFMT_R32G32_FLOAT: *convert = CONVERT_R32G32F; *format = GL_RGB; - *internal = GL_RGB32F_ARB; *type = GL_FLOAT; *target_bpp = 12; break; + case WINED3DFMT_D15S1: + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + *convert = CONVERT_D15S1; + *target_bpp = 4; + } + break; + + case WINED3DFMT_D24X4S4: + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + *convert = CONVERT_D24X4S4; + } + break; + + case WINED3DFMT_D24FS8: + if (GL_SUPPORT(ARB_DEPTH_BUFFER_FLOAT)) + { + *convert = CONVERT_D24FS8; + *target_bpp = 8; + } + break; + default: break; } @@ -1818,6 +1920,86 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ return WINED3D_OK; } +static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) +{ + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + IWineD3DPaletteImpl *pal = This->palette; + BOOL index_in_alpha = FALSE; + unsigned int i; + + /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets. + * Reading back the RGB output each lockrect (each frame as they lock the whole screen) + * 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. */ + index_in_alpha = primary_render_target_is_p8(device); + + if (!pal) + { + UINT dxVersion = ((IWineD3DImpl *)device->wineD3D)->dxVersion; + + /* 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) + { + /* 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 + { + TRACE("Using surface palette %p\n", pal); + /* Get the surface's palette */ + for (i = 0; i < 256; ++i) + { + table[i][0] = pal->palents[i].peRed; + table[i][1] = pal->palents[i].peGreen; + table[i][2] = pal->palents[i].peBlue; + + /* When index_in_alpha is set 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)) + { + table[i][3] = 0x00; + } + else if(pal->Flags & WINEDDPCAPS_ALPHA) + { + table[i][3] = pal->palents[i].peFlags; + } + else + { + table[i][3] = 0xFF; + } + } + } +} + static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This) { @@ -2176,82 +2358,83 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI float red = (*Source++); Dest[0] = green; Dest[1] = red; - Dest[2] = 1.0; + Dest[2] = 1.0f; Dest += 3; } } break; } + case CONVERT_D15S1: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const WORD *source = (const WORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + /* The depth data is normalized, so needs to be scaled, + * the stencil data isn't. Scale depth data by + * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */ + WORD d15 = source[x] >> 1; + DWORD d24 = (d15 << 9) + (d15 >> 6); + dest[x] = (d24 << 8) | (source[x] & 0x1); + } + } + break; + } + + case CONVERT_D24X4S4: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + /* Just need to clear out the X4 part. */ + dest[x] = source[x] & ~0xf0; + } + } + break; + } + + case CONVERT_D24FS8: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + float *dest_f = (float *)(dst + y * outpitch); + DWORD *dest_s = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8); + dest_s[x * 2 + 1] = source[x] & 0xff; + } + } + break; + } + default: - ERR("Unsupported conversation type %d\n", convert); + ERR("Unsupported conversion type %#x.\n", convert); } return WINED3D_OK; } -static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) { - IWineD3DPaletteImpl* pal = This->palette; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL index_in_alpha = FALSE; - int dxVersion = ( (IWineD3DImpl *) device->wineD3D)->dxVersion; - unsigned int i; - - /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets. - * Reading back the RGB output each lockrect (each frame as they lock the whole screen) - * 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. */ - index_in_alpha = primary_render_target_is_p8(device); - - if (pal == NULL) { - /* 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) { - /* 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 { - TRACE("Using surface palette %p\n", pal); - /* Get the surface's palette */ - for (i = 0; i < 256; i++) { - table[i][0] = pal->palents[i].peRed; - 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)) { - table[i][3] = 0x00; - } else if(pal->Flags & WINEDDPCAPS_ALPHA) { - table[i][3] = pal->palents[i].peFlags; - } else { - table[i][3] = 0xFF; - } - } - } -} - /* This function is used in case of 8bit paletted textures to upload the palette. It supports GL_EXT_paletted_texture and GL_ARB_fragment_program, support for other extensions like ATI_fragment_shaders is possible. */ +/* Context activation is done by the caller. */ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; BYTE table[256][4]; @@ -2263,7 +2446,9 @@ 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(This->glDescription.target,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table)); + ENTER_GL(); + GL_EXTCALL(glColorTableEXT(This->texture_target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table)); + LEAVE_GL(); } else { @@ -2271,6 +2456,8 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */ TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n"); + ENTER_GL(); + /* Create the fragment program if we don't have it */ if(!device->paletteConversionShader) { @@ -2309,7 +2496,9 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0)); /* Rebind the texture because it isn't bound anymore */ - glBindTexture(This->glDescription.target, This->glDescription.textureName); + glBindTexture(This->texture_target, This->texture_name); + + LEAVE_GL(); } } @@ -2383,7 +2572,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BO 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); + snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", + This, This->texture_target, This->texture_level, gen); IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer); } /* @@ -2406,6 +2596,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BO return WINED3D_OK; } +/* Context activation is done by the caller. */ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) { /* TODO: check for locks */ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; @@ -2421,30 +2612,31 @@ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL GLuint *name; TRACE("(%p) : Binding surface\n", This); - name = srgb ? &This->glDescription.srgbTextureName : &This->glDescription.textureName; + name = srgb ? &This->texture_name_srgb : &This->texture_name; if(!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); } ENTER_GL(); - if (!This->glDescription.level) { + if (!This->texture_level) + { if (!*name) { glGenTextures(1, name); checkGLcall("glGenTextures"); TRACE("Surface %p given name %d\n", This, *name); - glBindTexture(This->glDescription.target, *name); + glBindTexture(This->texture_target, *name); checkGLcall("glBindTexture"); - glTexParameteri(This->glDescription.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)"); - glTexParameteri(This->glDescription.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)"); - glTexParameteri(This->glDescription.target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)"); - glTexParameteri(This->glDescription.target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(This->texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MIN_FILTER, GL_NEAREST)"); - glTexParameteri(This->glDescription.target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(This->texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MAG_FILTER, GL_NEAREST)"); } /* This is where we should be reducing the amount of GLMemoryUsed */ @@ -2453,7 +2645,7 @@ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL ERR("Mipmap surface has a glTexture bound to it!\n"); } - glBindTexture(This->glDescription.target, This->glDescription.textureName); + glBindTexture(This->texture_target, *name); checkGLcall("glBindTexture"); LEAVE_GL(); @@ -2536,13 +2728,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, c } allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4); ENTER_GL(); - FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height); - glGetTexImage(GL_TEXTURE_2D, - This->glDescription.level, - GL_RGBA, - GL_UNSIGNED_INT_8_8_8_8_REV, - allocatedMemory); - checkGLcall("glTexImage2D"); + FIXME("Saving texture level %d width %d height %d\n", This->texture_level, width, height); + glGetTexImage(GL_TEXTURE_2D, This->texture_level, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, allocatedMemory); + checkGLcall("glGetTexImage"); if (tmpTexture) { glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(1, &tmpTexture); @@ -2743,9 +2931,15 @@ void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) { /* Flip the opengl texture */ { - glDescriptor tmp_desc = back->glDescription; - back->glDescription = front->glDescription; - front->glDescription = tmp_desc; + GLuint tmp; + + tmp = back->texture_name; + back->texture_name = front->texture_name; + front->texture_name = tmp; + + tmp = back->texture_name_srgb; + back->texture_name_srgb = front->texture_name_srgb; + front->texture_name_srgb = tmp; } { @@ -2779,7 +2973,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DS } if(override) { - /* DDraw sets this for the X11 surfaces, so don't confuse the user + /* DDraw sets this for the X11 surfaces, so don't confuse the user * FIXME("(%p) Target override is not supported by now\n", This); * Additionally, it isn't really possible to support triple-buffering * properly on opengl at all @@ -2832,7 +3026,7 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D ENTER_GL(); /* Bind the target texture */ - glBindTexture(This->glDescription.target, This->glDescription.textureName); + glBindTexture(This->texture_target, This->texture_name); checkGLcall("glBindTexture"); if(!swapchain) { TRACE("Reading from an offscreen target\n"); @@ -2847,26 +3041,30 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1); yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1); - if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) { + if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps)) + { FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n"); if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) { ERR("Texture filtering not supported in direct blit\n"); } - } else if((Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) && ((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) { + } + else if ((Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) + && ((yrel - 1.0f < -eps) || (yrel - 1.0f > eps))) + { ERR("Texture filtering not supported in direct blit\n"); } - if(upsidedown && - !((xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) && - !((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) { + if (upsidedown + && !((xrel - 1.0f < -eps) || (xrel - 1.0f > eps)) + && !((yrel - 1.0f < -eps) || (yrel - 1.0f > eps))) + { /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */ - glCopyTexSubImage2D(This->glDescription.target, - This->glDescription.level, - drect->x1, drect->y1, /* xoffset, yoffset */ - srect->x1, Src->currentDesc.Height - srect->y2, - drect->x2 - drect->x1, drect->y2 - drect->y1); + glCopyTexSubImage2D(This->texture_target, This->texture_level, + drect->x1 /*xoffset */, drect->y1 /* y offset */, + srect->x1, Src->currentDesc.Height - srect->y2, + drect->x2 - drect->x1, drect->y2 - drect->y1); } else { UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1; /* I have to process this row by row to swap the image, @@ -2876,25 +3074,22 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D * However, stretching in x direction can be avoided if not necessary */ for(row = drect->y1; row < drect->y2; row++) { - if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) { + if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps)) + { /* Well, that stuff works, but it's very slow. * find a better way instead */ UINT col; for(col = drect->x1; col < drect->x2; col++) { - glCopyTexSubImage2D(This->glDescription.target, - This->glDescription.level, - drect->x1 + col, row, /* xoffset, yoffset */ - srect->x1 + col * xrel, yoffset - (int) (row * yrel), - 1, 1); + glCopyTexSubImage2D(This->texture_target, This->texture_level, + drect->x1 + col /* x offset */, row /* y offset */, + srect->x1 + col * xrel, yoffset - (int) (row * yrel), 1, 1); } } else { - glCopyTexSubImage2D(This->glDescription.target, - This->glDescription.level, - drect->x1, row, /* xoffset, yoffset */ - srect->x1, yoffset - (int) (row * yrel), - drect->x2-drect->x1, 1); + glCopyTexSubImage2D(This->texture_target, This->texture_level, + drect->x1 /* x offset */, row /* y offset */, + srect->x1, yoffset - (int) (row * yrel), drect->x2-drect->x1, 1); } } } @@ -2914,17 +3109,19 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine float left, right, top, bottom; /* Texture coordinates */ UINT fbwidth = Src->currentDesc.Width; UINT fbheight = Src->currentDesc.Height; + struct wined3d_context *context; 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); + context = ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO; - if(!noBackBufferBackup && Src->glDescription.textureName == 0) { + if (!noBackBufferBackup && !Src->texture_name) + { /* Get it a description */ surface_internal_preload(SrcSurface, SRGB_RGB); } @@ -2933,27 +3130,30 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* 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(myDevice->activeContext->aux_buffers >= 2) { + if (context->aux_buffers >= 2) + { /* Got more than one aux buffer? Use the 2nd aux buffer */ drawBuffer = GL_AUX1; - } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && myDevice->activeContext->aux_buffers >= 1) { + } + else if ((swapchain || myDevice->offscreenBuffer == GL_BACK) && context->aux_buffers >= 1) + { /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */ drawBuffer = GL_AUX0; } if(noBackBufferBackup) { glGenTextures(1, &backup); - checkGLcall("glGenTextures\n"); + checkGLcall("glGenTextures"); glBindTexture(GL_TEXTURE_2D, backup); - checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)"); + checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)"); 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 */ - texture_target = Src->glDescription.target; - glBindTexture(texture_target, Src->glDescription.textureName); - checkGLcall("glBindTexture(texture_target, Src->glDescription.textureName)"); + texture_target = Src->texture_target; + glBindTexture(texture_target, Src->texture_name); + checkGLcall("glBindTexture(texture_target, Src->texture_name)"); glEnable(texture_target); checkGLcall("glEnable(texture_target)"); @@ -2980,14 +3180,14 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine /* No issue with overriding these - the sampler is dirty due to blit usage */ glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, - magLookup[Filter - WINED3DTEXF_NONE]); + wined3d_gl_mag_filter(magLookup, Filter)); checkGLcall("glTexParameteri"); glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, - minMipLookup[Filter].mip[WINED3DTEXF_NONE]); + wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE)); checkGLcall("glTexParameteri"); if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) { - src = backup ? backup : Src->glDescription.textureName; + src = backup ? backup : Src->texture_name; } else { glReadBuffer(GL_FRONT); checkGLcall("glReadBuffer(GL_FRONT)"); @@ -3069,14 +3269,15 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glEnd(); checkGLcall("glEnd and previous"); - if(texture_target != This->glDescription.target) { + if (texture_target != This->texture_target) + { glDisable(texture_target); - glEnable(This->glDescription.target); - texture_target = This->glDescription.target; + glEnable(This->texture_target); + texture_target = This->texture_target; } /* Now read the stretched and upside down image into the destination texture */ - glBindTexture(texture_target, This->glDescription.textureName); + glBindTexture(texture_target, This->texture_name); checkGLcall("glBindTexture"); glCopyTexSubImage2D(texture_target, 0, @@ -3096,26 +3297,27 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine glBindTexture(GL_TEXTURE_2D, backup); checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)"); } else { - if(texture_target != Src->glDescription.target) { + if (texture_target != Src->texture_target) + { glDisable(texture_target); - glEnable(Src->glDescription.target); - texture_target = Src->glDescription.target; + glEnable(Src->texture_target); + texture_target = Src->texture_target; } - glBindTexture(Src->glDescription.target, Src->glDescription.textureName); - checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)"); + glBindTexture(Src->texture_target, Src->texture_name); + checkGLcall("glBindTexture(Src->texture_target, Src->texture_name)"); } glBegin(GL_QUADS); /* top left */ - glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height); + glTexCoord2f(0.0f, (float)fbheight / (float)Src->pow2Height); glVertex2i(0, 0); /* bottom left */ - glTexCoord2f(0.0, 0.0); + glTexCoord2f(0.0f, 0.0f); glVertex2i(0, fbheight); /* bottom right */ - glTexCoord2f((float) fbwidth / (float) Src->pow2Width, 0.0); + glTexCoord2f((float)fbwidth / (float)Src->pow2Width, 0.0f); glVertex2i(fbwidth, Src->currentDesc.Height); /* top right */ @@ -3130,7 +3332,8 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine checkGLcall("glDisable(texture_target)"); /* Cleanup */ - if(src != Src->glDescription.textureName && src != backup) { + if (src != Src->texture_name && src != backup) + { glDeleteTextures(1, &src); checkGLcall("glDeleteTextures(1, &src)"); } @@ -3384,7 +3587,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering * backends. */ - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)) { + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) + && surface_can_stretch_rect(Src, This)) + { stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect, (IWineD3DSurface *)This, &rect, Filter, upsideDown); } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width || @@ -3446,8 +3651,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const Src->palette = This->palette; } - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) && - (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) == 0) { + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) + && !(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) + && surface_can_stretch_rect(Src, This)) + { 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 @@ -3511,67 +3718,76 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h; } + if (!is_identity_fixup(This->resource.format_desc->color_fixup)) + { + FIXME("Destination format %s has a fixup, this is not supported.\n", + debug_d3dformat(This->resource.format_desc->format)); + dump_color_fixup_desc(This->resource.format_desc->color_fixup); + } + + if (!myDevice->blitter->color_fixup_supported(Src->resource.format_desc->color_fixup)) + { + FIXME("Source format %s has an unsupported fixup:\n", + debug_d3dformat(Src->resource.format_desc->format)); + dump_color_fixup_desc(Src->resource.format_desc->color_fixup); + } + myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format_desc, - Src->glDescription.target, Src->pow2Width, Src->pow2Height); + Src->texture_target, Src->pow2Width, Src->pow2Height); ENTER_GL(); /* Bind the texture */ - glBindTexture(Src->glDescription.target, Src->glDescription.textureName); + glBindTexture(Src->texture_target, Src->texture_name); checkGLcall("glBindTexture"); /* Filtering for StretchRect */ - glTexParameteri(Src->glDescription.target, GL_TEXTURE_MAG_FILTER, - magLookup[Filter - WINED3DTEXF_NONE]); + glTexParameteri(Src->texture_target, GL_TEXTURE_MAG_FILTER, + wined3d_gl_mag_filter(magLookup, Filter)); checkGLcall("glTexParameteri"); - glTexParameteri(Src->glDescription.target, GL_TEXTURE_MIN_FILTER, - minMipLookup[Filter].mip[WINED3DTEXF_NONE]); + glTexParameteri(Src->texture_target, GL_TEXTURE_MIN_FILTER, + wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE)); checkGLcall("glTexParameteri"); - glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); checkGLcall("glTexEnvi"); /* This is for color keying */ if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) { glEnable(GL_ALPHA_TEST); - checkGLcall("glEnable GL_ALPHA_TEST"); + checkGLcall("glEnable(GL_ALPHA_TEST)"); /* 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); + glAlphaFunc(GL_NOTEQUAL, (float)Src->SrcBltCKey.dwColorSpaceLowValue / 256.0f); else - glAlphaFunc(GL_NOTEQUAL, 0.0); - checkGLcall("glAlphaFunc\n"); + glAlphaFunc(GL_NOTEQUAL, 0.0f); + checkGLcall("glAlphaFunc"); } else { glDisable(GL_ALPHA_TEST); - checkGLcall("glDisable GL_ALPHA_TEST"); + checkGLcall("glDisable(GL_ALPHA_TEST)"); } /* Draw a textured quad */ glBegin(GL_QUADS); - glColor3d(1.0f, 1.0f, 1.0f); + glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(glTexCoord[0], glTexCoord[2]); - glVertex3f(rect.x1, - rect.y1, - 0.0); + glVertex3f(rect.x1, rect.y1, 0.0f); glTexCoord2f(glTexCoord[0], glTexCoord[3]); - glVertex3f(rect.x1, rect.y2, 0.0); + glVertex3f(rect.x1, rect.y2, 0.0f); glTexCoord2f(glTexCoord[1], glTexCoord[3]); - glVertex3f(rect.x2, - rect.y2, - 0.0); + glVertex3f(rect.x2, rect.y2, 0.0f); glTexCoord2f(glTexCoord[1], glTexCoord[2]); - glVertex3f(rect.x2, - rect.y1, - 0.0); + glVertex3f(rect.x2, rect.y1, 0.0f); + glEnd(); checkGLcall("glEnd"); @@ -3580,8 +3796,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const checkGLcall("glDisable(GL_ALPHA_TEST)"); } - glBindTexture(Src->glDescription.target, 0); - checkGLcall("glBindTexture(Src->glDescription.target, 0)"); + glBindTexture(Src->texture_target, 0); + checkGLcall("glBindTexture(Src->texture_target, 0)"); /* Restore the color key parameters */ Src->CKeyFlags = oldCKeyFlags; @@ -3598,7 +3814,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const /* Flush in case the drawable is used by multiple GL contexts */ if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2)) - glFlush(); + wglFlush(); /* 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 @@ -3669,11 +3885,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const } TRACE("(%p) executing Render Target override, color = %x\n", This, color); - IWineD3DDeviceImpl_ClearSurface(myDevice, This, - 1, /* Number of rectangles */ - &rect, WINED3DCLEAR_TARGET, color, - 0.0 /* Z */, - 0 /* Stencil */); + IWineD3DDeviceImpl_ClearSurface(myDevice, This, 1 /* Number of rectangles */, + &rect, WINED3DCLEAR_TARGET, color, 0.0f /* Z */, 0 /* Stencil */); return WINED3D_OK; } } @@ -3706,7 +3919,7 @@ static HRESULT IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, const RECT *D depth = (float) DDBltFx->u5.dwFillDepth / (float) 0xffffffff; break; default: - depth = 0.0; + depth = 0.0f; ERR("Unexpected format for depth fill: %s\n", debug_d3dformat(This->resource.format_desc->format)); } @@ -3843,13 +4056,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) 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); + BOOL use_texture = (wined3d_settings.rendertargetlock_mode == RTL_READTEX); /* Check if we have hardware palette conversion if we have convert is set to NO_CONVERSION */ d3dfmt_get_conv(This, TRUE, use_texture, &format, &internal, &type, &convert, &bpp, FALSE); if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION)) { + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + /* 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); @@ -3857,6 +4072,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); /* Re-upload the palette */ + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); d3dfmt_p8_upload_palette(iface, convert); } else { if(!(This->Flags & SFLAG_INSYSMEM)) { @@ -3891,8 +4107,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; unsigned int pow2Width, pow2Height; - This->glDescription.textureName = 0; - This->glDescription.target = GL_TEXTURE_2D; + This->texture_name = 0; + This->texture_target = GL_TEXTURE_2D; /* Non-power2 support */ if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) { @@ -3908,11 +4124,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { This->pow2Height = pow2Height; if (pow2Width > This->currentDesc.Width || pow2Height > This->currentDesc.Height) { - WINED3DFORMAT Format = This->resource.format_desc->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_ATI2N) + if (This->resource.format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) { FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n", This, This->currentDesc.Width, This->currentDesc.Height); @@ -3950,10 +4163,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { */ if(This->Flags & SFLAG_NONPOW2 && GL_SUPPORT(ARB_TEXTURE_RECTANGLE) && !((This->resource.format_desc->format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) - && (wined3d_settings.rendertargetlock_mode == RTL_READTEX - || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX))) + && (wined3d_settings.rendertargetlock_mode == RTL_READTEX))) { - This->glDescription.target = GL_TEXTURE_RECTANGLE_ARB; + This->texture_target = GL_TEXTURE_RECTANGLE_ARB; This->pow2Width = This->currentDesc.Width; This->pow2Height = This->currentDesc.Height; This->Flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD); @@ -4073,6 +4285,7 @@ static void surface_get_depth_blt_info(GLenum target, GLsizei w, GLsizei h, stru } } +/* GL locking is done by the caller */ static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei w, GLsizei h, GLenum target) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; @@ -4082,14 +4295,14 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT); glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); + glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glDepthMask(GL_TRUE); - glBlendFunc(GL_ZERO, GL_ONE); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glViewport(0, 0, w, h); surface_get_depth_blt_info(target, w, h, &info); @@ -4130,7 +4343,9 @@ void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) { This->Flags |= location; } -void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { +/* Context activation is done by the caller. */ +void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location) +{ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; @@ -4164,8 +4379,9 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { /* 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)); - if (This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) { + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); + if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) + { glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); bind_target = GL_TEXTURE_RECTANGLE_ARB; } else { @@ -4173,16 +4389,13 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { bind_target = GL_TEXTURE_2D; } glBindTexture(bind_target, device->depth_blt_texture); - glCopyTexImage2D(bind_target, - This->glDescription.level, - This->resource.format_desc->glInternal, - 0, - 0, - This->currentDesc.Width, - This->currentDesc.Height, - 0); + glCopyTexImage2D(bind_target, This->texture_level, This->resource.format_desc->glInternal, + 0, 0, This->currentDesc.Width, This->currentDesc.Height, 0); glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); glBindTexture(bind_target, old_binding); @@ -4201,21 +4414,17 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { device->depth_blt_rb_h = This->currentDesc.Height; } - context_bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->dst_fbo); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->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); + context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, iface, FALSE); /* Do the actual blit */ surface_depth_blt(This, device->depth_blt_texture, This->currentDesc.Width, This->currentDesc.Height, bind_target); 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()"); - } + if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->current_fbo->id); + else context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); LEAVE_GL(); } else { @@ -4227,15 +4436,12 @@ void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) { ENTER_GL(); - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - checkGLcall("glBindFramebuffer()"); - surface_depth_blt(This, This->glDescription.textureName, This->currentDesc.Width, This->currentDesc.Height, This->glDescription.target); + context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL); + surface_depth_blt(This, This->texture_name, This->currentDesc.Width, + This->currentDesc.Height, This->texture_target); checkGLcall("depth_blt"); - if (device->activeContext->current_fbo) { - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->activeContext->current_fbo->id)); - checkGLcall("glBindFramebuffer()"); - } + if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->current_fbo->id); LEAVE_GL(); } else { @@ -4320,7 +4526,9 @@ static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float f->b = ((r->bottom * 2.0f) / h) - 1.0f; } -static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) { +static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) +{ + const struct wined3d_context *context; struct coords coords[4]; RECT rect; IWineD3DSwapChain *swapchain; @@ -4338,7 +4546,7 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT rect.bottom = This->currentDesc.Height; } - switch(This->glDescription.target) + switch (This->texture_target) { case GL_TEXTURE_2D: bind_target = GL_TEXTURE_2D; @@ -4423,23 +4631,24 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT break; default: - ERR("Unexpected texture target %#x\n", This->glDescription.target); + ERR("Unexpected texture target %#x\n", This->texture_target); return; } - ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); + context = ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); + ENTER_GL(); glEnable(bind_target); checkGLcall("glEnable(bind_target)"); - glBindTexture(bind_target, This->glDescription.textureName); - checkGLcall("bind_target, This->glDescription.textureName)"); + glBindTexture(bind_target, This->texture_name); + checkGLcall("glBindTexture(bind_target, This->texture_name)"); glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGLcall("glTexParameteri"); glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLcall("glTexParameteri"); - if (device->render_offscreen) + if (context->render_offscreen) { LONG tmp = rect.top; rect.top = rect.bottom; @@ -4471,7 +4680,7 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT /* 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)->frontBuffer == (IWineD3DSurface*)This || ((IWineD3DSwapChainImpl*)swapchain)->num_contexts >= 2) - glFlush(); + wglFlush(); IWineD3DSwapChain_Release(swapchain); } else { @@ -4552,11 +4761,12 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D /* Download the surface to system memory */ if(This->Flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) { - if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); surface_bind_and_dirtify(This, !(This->Flags & SFLAG_INTEXTURE)); surface_download_data(This); } else { + /* Note: It might be faster to download into a texture first. */ read_from_framebuffer(This, rect, This->resource.allocatedMemory, IWineD3DSurface_GetPitch(iface)); @@ -4583,6 +4793,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D * 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); + if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); surface_remove_pbo(This); } @@ -4634,7 +4845,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D } } - if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); surface_bind_and_dirtify(This, srgb); if(This->CKeyFlags & WINEDDSD_CKSRCBLT) { @@ -4829,7 +5040,6 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_BindTexture, IWineD3DSurfaceImpl_SaveSnapshot, IWineD3DSurfaceImpl_SetContainer, - IWineD3DSurfaceImpl_GetGlDesc, IWineD3DBaseSurfaceImpl_GetData, IWineD3DSurfaceImpl_SetFormat, IWineD3DSurfaceImpl_PrivateSetup, @@ -4842,18 +5052,24 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = #define GLINFO_LOCATION device->adapter->gl_info static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +/* Context activation is done by the caller. */ static void ffp_blit_free(IWineD3DDevice *iface) { } +/* Context activation is done by the caller. */ static HRESULT ffp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatDesc *format_desc, GLenum textype, UINT width, UINT height) { + ENTER_GL(); glEnable(textype); checkGLcall("glEnable(textype)"); + LEAVE_GL(); return WINED3D_OK; } +/* Context activation is done by the caller. */ static void ffp_blit_unset(IWineD3DDevice *iface) { IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + ENTER_GL(); glDisable(GL_TEXTURE_2D); checkGLcall("glDisable(GL_TEXTURE_2D)"); if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { @@ -4864,6 +5080,7 @@ static void ffp_blit_unset(IWineD3DDevice *iface) { glDisable(GL_TEXTURE_RECTANGLE_ARB); checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); } + LEAVE_GL(); } static BOOL ffp_blit_color_fixup_supported(struct color_fixup_desc fixup) diff --git a/reactos/dll/directx/wine/wined3d/surface_base.c b/reactos/dll/directx/wine/wined3d/surface_base.c index d487f80e10a..5c00b2b8c3e 100644 --- a/reactos/dll/directx/wine/wined3d/surface_base.c +++ b/reactos/dll/directx/wine/wined3d/surface_base.c @@ -30,8 +30,6 @@ #include "wine/port.h" #include "wined3d_private.h" -#include - WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); /* See also float_16_to_32() in wined3d_private.h */ @@ -43,26 +41,26 @@ static inline unsigned short float_32_to_16(const float *in) unsigned short ret; /* Deal with special numbers */ - if(*in == 0.0) return 0x0000; + if (*in == 0.0f) return 0x0000; if(isnan(*in)) return 0x7C01; - if(isinf(*in)) return (*in < 0.0 ? 0xFC00 : 0x7c00); + if (isinf(*in)) return (*in < 0.0f ? 0xFC00 : 0x7c00); if(tmp < pow(2, 10)) { do { - tmp = tmp * 2.0; + tmp = tmp * 2.0f; exp--; }while(tmp < pow(2, 10)); } else if(tmp >= pow(2, 11)) { do { - tmp /= 2.0; + tmp /= 2.0f; exp++; }while(tmp >= pow(2, 11)); } mantissa = (unsigned int) tmp; - if(tmp - mantissa >= 0.5) mantissa++; /* round to nearest, away from zero */ + if(tmp - mantissa >= 0.5f) mantissa++; /* round to nearest, away from zero */ exp += 10; /* Normalize the mantissa */ exp += 15; /* Exponent is encoded with excess 15 */ @@ -80,7 +78,7 @@ static inline unsigned short float_32_to_16(const float *in) ret = (exp << 10) | (mantissa & 0x3ff); } - ret |= ((*in < 0.0 ? 1 : 0) << 15); /* Add the sign */ + ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */ return ret; } @@ -181,15 +179,17 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSU IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; TRACE("(%p) : copying into %p\n", This, pDesc); - if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format_desc->format; - if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType; - if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage; - if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool; - if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */ - if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType; - if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality; - if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width; - if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height; + + pDesc->format = This->resource.format_desc->format; + pDesc->resource_type = This->resource.resourceType; + pDesc->usage = This->resource.usage; + pDesc->pool = This->resource.pool; + pDesc->size = This->resource.size; /* dx8 only */ + pDesc->multisample_type = This->currentDesc.MultiSampleType; + pDesc->multisample_quality = This->currentDesc.MultiSampleQuality; + pDesc->width = This->currentDesc.Width; + pDesc->height = This->currentDesc.Height; + return WINED3D_OK; } @@ -332,19 +332,19 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - WINED3DFORMAT format = This->resource.format_desc->format; + const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; DWORD ret; TRACE("(%p)\n", This); - /* DXTn formats don't have exact pitches as they are to the new row of blocks, - where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5) - ie pitch = (width/4) * bytes per block */ - if (format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */ - ret = ((This->currentDesc.Width + 3) >> 2) << 3; - else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 || - format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */ - ret = ((This->currentDesc.Width + 3) >> 2) << 4; - else { + if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + /* Since compressed formats are block based, pitch means the amount of + * bytes to the next row of block rather than the next row of pixels. */ + UINT row_block_count = (This->currentDesc.Width + format_desc->block_width - 1) / format_desc->block_width; + ret = row_block_count * format_desc->block_byte_count; + } + else + { unsigned char alignment = This->resource.wineD3DDevice->surface_alignment; ret = This->resource.format_desc->byte_count * This->currentDesc.Width; /* Bytes / row */ ret = (ret + alignment - 1) & ~(alignment - 1); @@ -519,20 +519,9 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3D } TRACE("(%p) : Setting texture format to (%d,%s)\n", This, format, debug_d3dformat(format)); - if (format == WINED3DFMT_UNKNOWN) { - This->resource.size = 0; - } else if (format == WINED3DFMT_DXT1) { - /* DXT1 is half byte per pixel */ - This->resource.size = ((max(This->pow2Width, 4) * format_desc->byte_count) * max(This->pow2Height, 4)) >> 1; - } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 || - format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) { - This->resource.size = ((max(This->pow2Width, 4) * format_desc->byte_count) * max(This->pow2Height, 4)); - } else { - unsigned char alignment = This->resource.wineD3DDevice->surface_alignment; - This->resource.size = ((This->pow2Width * format_desc->byte_count) + alignment - 1) & ~(alignment - 1); - This->resource.size *= This->pow2Height; - } + This->resource.size = surface_calculate_size(format_desc, This->resource.wineD3DDevice->surface_alignment, + This->pow2Width, This->pow2Height); This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0; @@ -735,6 +724,25 @@ static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst, } } +static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + unsigned int x, y; + + TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const DWORD *src_line = (const DWORD *)(src + y * pitch_in); + DWORD *dst_line = (DWORD *)(dst + y * pitch_out); + + for (x = 0; x < w; ++x) + { + dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff); + } + } +} + struct d3dfmt_convertor_desc { WINED3DFORMAT from, to; void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h); @@ -744,6 +752,7 @@ static const struct d3dfmt_convertor_desc convertors[] = { {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float}, {WINED3DFMT_R5G6B5, WINED3DFMT_X8R8G8B8, convert_r5g6b5_x8r8g8b8}, + {WINED3DFMT_A8R8G8B8, WINED3DFMT_X8R8G8B8, convert_a8r8g8b8_x8r8g8b8}, }; static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to) @@ -781,10 +790,9 @@ static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, 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 */, + IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.wineD3DDevice, source->currentDesc.Width, + source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret, + 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */, 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source), NULL /* parent */); if(!ret) { ERR("Failed to create a destination surface for conversion\n"); @@ -1127,8 +1135,6 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *D dstwidth = xdst.right - xdst.left; width = (xdst.right - xdst.left) * bpp; - assert(width <= dlock.Pitch); - if (DestRect && Src != This) dbuf = dlock.pBits; else @@ -1629,7 +1635,6 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dst slock.Pitch = dlock.Pitch; /* Since slock was originally copied from this surface's description, we can just reuse it */ - assert(This->resource.allocatedMemory != NULL); 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 = Src->resource.format_desc; @@ -1650,63 +1655,39 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dst dEntry = This->resource.format_desc; } - /* Handle first the FOURCC surfaces... */ - if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_FOURCC) + /* Handle compressed surfaces first... */ + if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) { - UINT block_width; - UINT block_height; - UINT block_byte_size; + UINT row_block_count; - TRACE("Fourcc -> Fourcc copy\n"); + TRACE("compressed -> compressed copy\n"); if (trans) - FIXME("trans arg not supported when a FOURCC surface is involved\n"); + FIXME("trans arg not supported when a compressed surface is involved\n"); if (dstx || dsty) FIXME("offset for destination surface is not supported\n"); if (Src->resource.format_desc->format != This->resource.format_desc->format) { - FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n"); + FIXME("compressed -> compressed copy only supported for the same type of surface\n"); ret = WINED3DERR_WRONGTEXTUREFORMAT; goto error; } - if (This->resource.format_desc->format == WINED3DFMT_DXT1) + row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width; + for (y = 0; y < h; y += dEntry->block_height) { - block_width = 4; - block_height = 4; - block_byte_size = 8; - } - else if (This->resource.format_desc->format == WINED3DFMT_DXT2 - || This->resource.format_desc->format == WINED3DFMT_DXT3 - || This->resource.format_desc->format == WINED3DFMT_DXT4 - || This->resource.format_desc->format == WINED3DFMT_DXT5) - { - block_width = 4; - block_height = 4; - block_byte_size = 16; - } - else - { - FIXME("Unsupported FourCC format %s.\n", debug_d3dformat(This->resource.format_desc->format)); - block_width = 1; - block_height = 1; - block_byte_size = This->resource.format_desc->byte_count; - } - - for (y = 0; y < h; y += block_height) - { - memcpy(dbuf, sbuf, (w / block_width) * block_byte_size); + memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count); dbuf += dlock.Pitch; sbuf += slock.Pitch; } goto error; } - if ((sEntry->Flags & WINED3DFMT_FLAG_FOURCC) && !(dEntry->Flags & WINED3DFMT_FLAG_FOURCC)) + if ((sEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED)) { /* TODO: Use the libtxc_dxtn.so shared library to do * software decompression */ - ERR("DXTC decompression not supported by now\n"); + ERR("Software decompression not supported.\n"); goto error; } @@ -1844,32 +1825,24 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DL } else { + const struct GlPixelFormatDesc *format_desc = This->resource.format_desc; + TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); - /* DXTn textures are based on compressed blocks of 4x4 pixels, each - * 16 bytes large (8 bytes in case of DXT1). Because of that Pitch has - * slightly different meaning compared to regular textures. For DXTn - * textures Pitch is the size of a row of blocks, 4 high and "width" - * long. The x offset is calculated differently as well, since moving 4 - * pixels to the right actually moves an entire 4x4 block to right, ie - * 16 bytes (8 in case of DXT1). */ - if (This->resource.format_desc->format == WINED3DFMT_DXT1) + if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) { - pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 2); - } - else if (This->resource.format_desc->format == WINED3DFMT_DXT2 - || This->resource.format_desc->format == WINED3DFMT_DXT3 - || This->resource.format_desc->format == WINED3DFMT_DXT4 - || This->resource.format_desc->format == WINED3DFMT_DXT5) - { - pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 4); + /* Compressed textures are block based, so calculate the offset of + * the block that contains the top-left pixel of the locked rectangle. */ + pLockedRect->pBits = This->resource.allocatedMemory + + ((pRect->top / format_desc->block_height) * pLockedRect->Pitch) + + ((pRect->left / format_desc->block_width) * format_desc->block_byte_count); } else { pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + - (pRect->left * This->resource.format_desc->byte_count); + (pRect->left * format_desc->byte_count); } This->lockedRect.left = pRect->left; This->lockedRect.top = pRect->top; diff --git a/reactos/dll/directx/wine/wined3d/surface_gdi.c b/reactos/dll/directx/wine/wined3d/surface_gdi.c index 0ad65e01a98..02467829e83 100644 --- a/reactos/dll/directx/wine/wined3d/surface_gdi.c +++ b/reactos/dll/directx/wine/wined3d/surface_gdi.c @@ -29,12 +29,34 @@ #include "wine/port.h" #include "wined3d_private.h" -#include #include /* Use the d3d_surface debug channel to have one channel for all surfaces */ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); +void surface_gdi_cleanup(IWineD3DSurfaceImpl *This) +{ + TRACE("(%p) : Cleaning up.\n", This); + + if (This->Flags & SFLAG_DIBSECTION) + { + /* Release the DC. */ + SelectObject(This->hDC, This->dib.holdbitmap); + DeleteDC(This->hDC); + /* Release the DIB section. */ + DeleteObject(This->dib.DIBsection); + This->dib.bitmap_data = NULL; + This->resource.allocatedMemory = NULL; + } + + if (This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem((IWineD3DSurface *)This, NULL); + if (This->overlay_dest) list_remove(&This->overlay_entry); + + HeapFree(GetProcessHeap(), 0, This->palette9); + + resource_cleanup((IWineD3DResource *)This); +} + /***************************************************************************** * IWineD3DSurface::Release, GDI version * @@ -46,32 +68,15 @@ static ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); - if (ref == 0) { - TRACE("(%p) : cleaning up\n", This); - if(This->Flags & SFLAG_DIBSECTION) { - /* Release the DC */ - SelectObject(This->hDC, This->dib.holdbitmap); - DeleteDC(This->hDC); - /* Release the DIB section */ - DeleteObject(This->dib.DIBsection); - This->dib.bitmap_data = NULL; - This->resource.allocatedMemory = NULL; - } - if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL); + if (!ref) + { + surface_gdi_cleanup(This); - HeapFree(GetProcessHeap(), 0, This->palette9); - - resource_cleanup((IWineD3DResource *)iface); - - if(This->overlay_dest) { - list_remove(&This->overlay_entry); - } - - TRACE("(%p) Released\n", This); + TRACE("(%p) Released.\n", This); HeapFree(GetProcessHeap(), 0, This); - } + return ref; } @@ -178,7 +183,8 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface) 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); + snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", + This, This->texture_target, This->texture_level, gen); IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer); } /* @@ -194,7 +200,10 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface) /* Tell the swapchain to update the screen */ if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { - x11_copy_to_screen(swapchain, &This->lockedRect); + if(iface == swapchain->frontBuffer) + { + x11_copy_to_screen(swapchain, &This->lockedRect); + } IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } @@ -485,7 +494,10 @@ static HRESULT WINAPI IWineGDISurfaceImpl_RealizePalette(IWineD3DSurface *iface) /* Tell the swapchain to update the screen */ if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) { - x11_copy_to_screen(swapchain, NULL); + if(iface == swapchain->frontBuffer) + { + x11_copy_to_screen(swapchain, NULL); + } IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } @@ -536,12 +548,6 @@ IWineGDISurfaceImpl_PrivateSetup(IWineD3DSurface *iface) return WINED3D_OK; } -static void WINAPI IWineGDISurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - FIXME("(%p) : Should not be called on a GDI surface\n", This); - *glDescription = NULL; -} - static HRESULT WINAPI IWineGDISurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; @@ -671,7 +677,6 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DBaseSurfaceImpl_BindTexture, IWineGDISurfaceImpl_SaveSnapshot, IWineD3DBaseSurfaceImpl_SetContainer, - IWineGDISurfaceImpl_GetGlDesc, IWineD3DBaseSurfaceImpl_GetData, IWineD3DBaseSurfaceImpl_SetFormat, IWineGDISurfaceImpl_PrivateSetup, diff --git a/reactos/dll/directx/wine/wined3d/swapchain.c b/reactos/dll/directx/wine/wined3d/swapchain.c index 12f812eb316..d8d3733f56d 100644 --- a/reactos/dll/directx/wine/wined3d/swapchain.c +++ b/reactos/dll/directx/wine/wined3d/swapchain.c @@ -45,26 +45,36 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB IWineD3DSwapChain_SetGammaRamp(iface, 0, &This->orig_gamma); - /* release the ref to the front and back buffer parents */ - if(This->frontBuffer) { + /* Release the swapchain's draw buffers. Make sure This->backBuffer[0] is + * the last buffer to be destroyed, FindContext() depends on that. */ + if (This->frontBuffer) + { IWineD3DSurface_SetContainer(This->frontBuffer, 0); - if(D3DCB_DestroyRenderTarget(This->frontBuffer) > 0) { - FIXME("(%p) Something's still holding the front buffer\n",This); + if (D3DCB_DestroyRenderTarget(This->frontBuffer)) + { + FIXME("(%p) Something's still holding the front buffer (%p).\n", + This, This->frontBuffer); } + This->frontBuffer = NULL; } - if(This->backBuffer) { - UINT i; - for(i = 0; i < This->presentParms.BackBufferCount; i++) { + if (This->backBuffer) + { + UINT i = This->presentParms.BackBufferCount; + + while (i--) + { IWineD3DSurface_SetContainer(This->backBuffer[i], 0); - if(D3DCB_DestroyRenderTarget(This->backBuffer[i]) > 0) { - FIXME("(%p) Something's still holding the back buffer\n",This); - } + if (D3DCB_DestroyRenderTarget(This->backBuffer[i])) + FIXME("(%p) Something's still holding back buffer %u (%p).\n", + This, i, This->backBuffer[i]); } HeapFree(GetProcessHeap(), 0, This->backBuffer); + This->backBuffer = NULL; } - for(i = 0; i < This->num_contexts; i++) { + for (i = 0; i < This->num_contexts; ++i) + { DestroyContext(This->wineD3DDevice, This->context[i]); } /* Restore the screen resolution if we rendered in fullscreen @@ -111,9 +121,9 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO cursor.resource.pool = WINED3DPOOL_SCRATCH; cursor.resource.format_desc = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &This->wineD3DDevice->adapter->gl_info); cursor.resource.resourceType = WINED3DRTYPE_SURFACE; - cursor.glDescription.textureName = This->wineD3DDevice->cursorTexture; - cursor.glDescription.target = GL_TEXTURE_2D; - cursor.glDescription.level = 0; + cursor.texture_name = This->wineD3DDevice->cursorTexture; + cursor.texture_target = GL_TEXTURE_2D; + cursor.texture_level = 0; cursor.currentDesc.Width = This->wineD3DDevice->cursorWidth; cursor.currentDesc.Height = This->wineD3DDevice->cursorHeight; cursor.glRect.left = 0; @@ -131,7 +141,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO if (This->presentParms.Windowed) { MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2); } - IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *) &cursor, NULL, WINEDDBLT_KEYSRC, NULL, WINED3DTEXF_NONE); + IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *)&cursor, + NULL, WINEDDBLT_KEYSRC, NULL, WINED3DTEXF_POINT); } if(This->wineD3DDevice->logo_surface) { /* Blit the logo into the upper left corner of the drawable */ @@ -223,7 +234,7 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO TRACE("Clearing the color buffer with cyan color\n"); IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, - WINED3DCLEAR_TARGET, 0xff00ffff, 1.0, 0); + WINED3DCLEAR_TARGET, 0xff00ffff, 1.0f, 0); } if(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_INSYSMEM || @@ -371,10 +382,11 @@ const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl = IWineD3DBaseSwapChainImpl_GetGammaRamp }; -WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) { - WineD3DContext *ctx; +struct wined3d_context *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) +{ IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface; - WineD3DContext **newArray; + struct wined3d_context **newArray; + struct wined3d_context *ctx; TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId()); @@ -401,10 +413,11 @@ WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain * return ctx; } -void get_drawable_size_swapchain(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) { +void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->current_rt; /* The drawable size of an onscreen drawable is the surface size. - * (Actually: The window size, but the surface is created in window size) - */ - *width = This->currentDesc.Width; - *height = This->currentDesc.Height; + * (Actually: The window size, but the surface is created in window size) */ + *width = surface->currentDesc.Width; + *height = surface->currentDesc.Height; } diff --git a/reactos/dll/directx/wine/wined3d/texture.c b/reactos/dll/directx/wine/wined3d/texture.c index dda43537cfc..dd8f32ed7dc 100644 --- a/reactos/dll/directx/wine/wined3d/texture.c +++ b/reactos/dll/directx/wine/wined3d/texture.c @@ -25,11 +25,271 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); -#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + +#define GLINFO_LOCATION (*gl_info) + +static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) +{ + /* Override the IWineD3DResource PreLoad method. */ + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + unsigned int i; + BOOL srgb_mode; + BOOL *dirty; + + TRACE("(%p) : About to load texture.\n", This); + + switch (srgb) + { + case SRGB_RGB: + srgb_mode = FALSE; + break; + + case SRGB_BOTH: + texture_internal_preload(iface, SRGB_RGB); + /* Fallthrough */ + + case SRGB_SRGB: + srgb_mode = TRUE; + break; + + default: + srgb_mode = This->baseTexture.is_srgb; + break; + } + dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; + + if (!device->isInDraw) + { + /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, + * thus no danger of recursive calls. */ + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + } + + if (This->resource.format_desc->format == WINED3DFMT_P8 + || This->resource.format_desc->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 (*dirty) + { + for (i = 0; i < This->baseTexture.levels; ++i) + { + IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); + } + } + else + { + TRACE("(%p) Texture not dirty, nothing to do.\n", iface); + } + + /* No longer dirty. */ + *dirty = FALSE; +} + +static void texture_cleanup(IWineD3DTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb) +{ + unsigned int i; + + TRACE("(%p) : Cleaning up\n", This); + + for (i = 0; i < This->baseTexture.levels; ++i) + { + if (This->surfaces[i]) + { + /* Clean out the texture name we gave to the surface so that the + * surface doesn't try and release it */ + surface_set_texture_name(This->surfaces[i], 0, TRUE); + surface_set_texture_name(This->surfaces[i], 0, FALSE); + surface_set_texture_target(This->surfaces[i], 0); + IWineD3DSurface_SetContainer(This->surfaces[i], 0); + surface_destroy_cb(This->surfaces[i]); + } + } + + TRACE("(%p) : Cleaning up base texture\n", This); + basetexture_cleanup((IWineD3DBaseTexture *)This); +} + +HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) +{ + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + UINT pow2_width, pow2_height; + UINT tmp_w, tmp_h; + unsigned int i; + HRESULT hr; + + /* 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", texture); + return WINED3DERR_INVALIDCALL; + } + + /* Non-power2 support. */ + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) + { + pow2_width = width; + pow2_height = height; + } + else + { + /* Find the nearest pow2 match. */ + pow2_width = pow2_height = 1; + while (pow2_width < width) pow2_width <<= 1; + while (pow2_height < height) pow2_height <<= 1; + + if (pow2_width != width || pow2_height != height) + { + if (levels > 1) + { + WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n"); + return WINED3DERR_INVALIDCALL; + } + levels = 1; + } + } + + /* Calculate levels for mip mapping. */ + if (usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + levels = 1; + } + else if (!levels) + { + levels = wined3d_log2i(max(width, height)) + 1; + TRACE("Calculated levels = %u.\n", levels); + } + + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, + WINED3DRTYPE_TEXTURE, device, 0, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize basetexture, returning %#x.\n", hr); + return hr; + } + + /* 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). The reason is that EXT_PALETTED_TEXTURE + * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */ + if (GL_SUPPORT(WINE_NORMALIZED_TEXRECT) && (width != pow2_width || height != pow2_height)) + { + texture->baseTexture.pow2Matrix[0] = 1.0f; + texture->baseTexture.pow2Matrix[5] = 1.0f; + texture->baseTexture.pow2Matrix[10] = 1.0f; + texture->baseTexture.pow2Matrix[15] = 1.0f; + texture->target = GL_TEXTURE_2D; + texture->cond_np2 = TRUE; + texture->baseTexture.minMipLookup = minMipLookup_noFilter; + } + else if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE) && (width != pow2_width || height != pow2_height) + && !((format_desc->format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) + && (wined3d_settings.rendertargetlock_mode == RTL_READTEX))) + { + if ((width != 1) || (height != 1)) texture->baseTexture.pow2Matrix_identity = FALSE; + + texture->baseTexture.pow2Matrix[0] = (float)width; + texture->baseTexture.pow2Matrix[5] = (float)height; + texture->baseTexture.pow2Matrix[10] = 1.0f; + texture->baseTexture.pow2Matrix[15] = 1.0f; + texture->target = GL_TEXTURE_RECTANGLE_ARB; + texture->cond_np2 = TRUE; + + if(texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) + { + texture->baseTexture.minMipLookup = minMipLookup_noMip; + } + else + { + texture->baseTexture.minMipLookup = minMipLookup_noFilter; + } + } + else + { + if ((width != pow2_width) || (height != pow2_height)) + { + texture->baseTexture.pow2Matrix_identity = FALSE; + texture->baseTexture.pow2Matrix[0] = (((float)width) / ((float)pow2_width)); + texture->baseTexture.pow2Matrix[5] = (((float)height) / ((float)pow2_height)); + } + else + { + texture->baseTexture.pow2Matrix[0] = 1.0f; + texture->baseTexture.pow2Matrix[5] = 1.0f; + } + + texture->baseTexture.pow2Matrix[10] = 1.0f; + texture->baseTexture.pow2Matrix[15] = 1.0f; + texture->target = GL_TEXTURE_2D; + texture->cond_np2 = FALSE; + } + TRACE("xf(%f) yf(%f)\n", texture->baseTexture.pow2Matrix[0], texture->baseTexture.pow2Matrix[5]); + + /* Generate all the surfaces. */ + tmp_w = width; + tmp_h = height; + for (i = 0; i < texture->baseTexture.levels; ++i) + { + /* Use the callback to create the texture surface. */ + hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format, + usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i]); + if (FAILED(hr) || ((IWineD3DSurfaceImpl *)texture->surfaces[i])->Flags & SFLAG_OVERSIZE) + { + FIXME("Failed to create surface %p, hr %#x\n", texture, hr); + texture->surfaces[i] = NULL; + texture_cleanup(texture, D3DCB_DefaultDestroySurface); + return hr; + } + + IWineD3DSurface_SetContainer(texture->surfaces[i], (IWineD3DBase *)texture); + TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[i]); + surface_set_texture_target(texture->surfaces[i], texture->target); + /* Calculate the next mipmap level. */ + tmp_w = max(1, tmp_w >> 1); + tmp_h = max(1, tmp_h >> 1); + } + texture->baseTexture.internal_preload = texture_internal_preload; + + return WINED3D_OK; +} + +#undef GLINFO_LOCATION /* ******************************************* IWineD3DTexture IUnknown parts follow ******************************************* */ + +#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + static HRESULT WINAPI IWineD3DTextureImpl_QueryInterface(IWineD3DTexture *iface, REFIID riid, LPVOID *ppobj) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; @@ -92,61 +352,6 @@ static DWORD WINAPI IWineD3DTextureImpl_GetPriority(IWineD3DTexture *iface) { return resource_get_priority((IWineD3DResource *)iface); } -void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { - - /* Override the IWineD3DResource PreLoad method */ - unsigned int i; - IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL srgb_mode; - BOOL *dirty; - - TRACE("(%p) : About to load texture\n", This); - - switch(srgb) { - case SRGB_RGB: srgb_mode = FALSE; break; - case SRGB_BOTH: texture_internal_preload(iface, SRGB_RGB); - case SRGB_SRGB: srgb_mode = TRUE; break; - /* DONTKNOW, and shut up the compiler */ - default: srgb_mode = This->baseTexture.is_srgb; break; - } - dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; - - if(!device->isInDraw) { - /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, thus no danger of - * recursive calls - */ - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - - if (This->resource.format_desc->format == WINED3DFMT_P8 - || This->resource.format_desc->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 (*dirty) { - for (i = 0; i < This->baseTexture.levels; i++) { - IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); - } - } else { - TRACE("(%p) Texture not dirty, nothing to do\n" , iface); - } - - /* No longer dirty */ - *dirty = FALSE; - - return ; -} - static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { texture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); } @@ -213,6 +418,7 @@ static BOOL WINAPI IWineD3DTextureImpl_GetDirty(IWineD3DTexture *iface) { return basetexture_get_dirty((IWineD3DBaseTexture *)iface); } +/* Context activation is done by the caller. */ static HRESULT WINAPI IWineD3DTextureImpl_BindTexture(IWineD3DTexture *iface, BOOL srgb) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; BOOL set_gl_texture_desc; @@ -271,33 +477,13 @@ static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) { return This->cond_np2; } -static void WINAPI IWineD3DTextureImpl_ApplyStateChanges(IWineD3DTexture *iface, - const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], - const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) { - TRACE("(%p) : relay to BaseTexture\n", iface); - basetexture_apply_state_changes((IWineD3DBaseTexture *)iface, textureStates, samplerStates); -} - /* ******************************************* IWineD3DTexture IWineD3DTexture parts follow ******************************************* */ static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - unsigned int i; - TRACE("(%p) : Cleaning up\n",This); - for (i = 0; i < This->baseTexture.levels; i++) { - if (This->surfaces[i] != NULL) { - /* Clean out the texture name we gave to the surface so that the surface doesn't try and release it */ - surface_set_texture_name(This->surfaces[i], 0, TRUE); - surface_set_texture_name(This->surfaces[i], 0, FALSE); - surface_set_texture_target(This->surfaces[i], 0); - IWineD3DSurface_SetContainer(This->surfaces[i], 0); - D3DCB_DestroySurface(This->surfaces[i]); - } - } - TRACE("(%p) : cleaning up base texture\n", This); - basetexture_cleanup((IWineD3DBaseTexture *)iface); + texture_cleanup(This, D3DCB_DestroySurface); /* free the object */ HeapFree(GetProcessHeap(), 0, This); } @@ -401,7 +587,6 @@ const IWineD3DTextureVtbl IWineD3DTexture_Vtbl = IWineD3DTextureImpl_BindTexture, IWineD3DTextureImpl_GetTextureDimensions, IWineD3DTextureImpl_IsCondNP2, - IWineD3DTextureImpl_ApplyStateChanges, /* IWineD3DTexture */ IWineD3DTextureImpl_Destroy, IWineD3DTextureImpl_GetLevelDesc, diff --git a/reactos/dll/directx/wine/wined3d/utils.c b/reactos/dll/directx/wine/wined3d/utils.c index d6973725748..3c25ebeb3e0 100644 --- a/reactos/dll/directx/wine/wined3d/utils.c +++ b/reactos/dll/directx/wine/wined3d/utils.c @@ -91,14 +91,14 @@ static const struct StaticPixelFormatDesc formats[] = {WINED3DFMT_A8_UNORM, 0x000000ff, 0x0, 0x0, 0x0, 1, 0, 0, FALSE}, {WINED3DFMT_A8R3G3B2, 0x0000ff00, 0x000000e0, 0x0000001c, 0x00000003, 2, 0, 0, FALSE}, {WINED3DFMT_X4R4G4B4, 0x0, 0x00000f00, 0x000000f0, 0x0000000f, 2, 0, 0, FALSE}, - {WINED3DFMT_R10G10B10A2_UNORM, 0xb0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, - {WINED3DFMT_R10G10B10A2_UINT, 0xb0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, - {WINED3DFMT_R10G10B10A2_SNORM, 0xb0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, + {WINED3DFMT_R10G10B10A2_UNORM, 0xc0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, + {WINED3DFMT_R10G10B10A2_UINT, 0xc0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, + {WINED3DFMT_R10G10B10A2_SNORM, 0xc0000000, 0x000003ff, 0x000ffc00, 0x3ff00000, 4, 0, 0, FALSE}, {WINED3DFMT_R8G8B8A8_UNORM, 0xff000000, 0x000000ff, 0x0000ff00, 0x00ff0000, 4, 0, 0, FALSE}, {WINED3DFMT_R8G8B8A8_UINT, 0xff000000, 0x000000ff, 0x0000ff00, 0x00ff0000, 4, 0, 0, FALSE}, {WINED3DFMT_X8B8G8R8, 0x0, 0x000000ff, 0x0000ff00, 0x00ff0000, 4, 0, 0, FALSE}, {WINED3DFMT_R16G16_UNORM, 0x0, 0x0000ffff, 0xffff0000, 0x0, 4, 0, 0, FALSE}, - {WINED3DFMT_A2R10G10B10, 0xb0000000, 0x3ff00000, 0x000ffc00, 0x000003ff, 4, 0, 0, FALSE}, + {WINED3DFMT_A2R10G10B10, 0xc0000000, 0x3ff00000, 0x000ffc00, 0x000003ff, 4, 0, 0, FALSE}, {WINED3DFMT_R16G16B16A16_UNORM, 0x1, 0x0000ffff, 0xffff0000, 0x0, 8, 0, 0, FALSE}, /* Luminance */ {WINED3DFMT_L8, 0x0, 0x0, 0x0, 0x0, 1, 0, 0, FALSE}, @@ -134,6 +134,24 @@ static const struct StaticPixelFormatDesc formats[] = {WINED3DFMT_NVHS, 0x0, 0x0, 0x0, 0x0, 2, 0, 0, TRUE }, }; +struct wined3d_format_compression_info +{ + WINED3DFORMAT format; + UINT block_width; + UINT block_height; + UINT block_byte_count; +}; + +static const struct wined3d_format_compression_info format_compression_info[] = +{ + {WINED3DFMT_DXT1, 4, 4, 8}, + {WINED3DFMT_DXT2, 4, 4, 16}, + {WINED3DFMT_DXT3, 4, 4, 16}, + {WINED3DFMT_DXT4, 4, 4, 16}, + {WINED3DFMT_DXT5, 4, 4, 16}, + {WINED3DFMT_ATI2N, 4, 4, 16}, +}; + struct wined3d_format_vertex_info { WINED3DFORMAT format; @@ -170,6 +188,7 @@ typedef struct { WINED3DFORMAT fmt; GLint glInternal, glGammaInternal, rtInternal, glFormat, glType; unsigned int Flags; + GL_SupportedExt extension; } GlPixelFormatDescTemplate; /***************************************************************************** @@ -181,10 +200,8 @@ typedef struct { static const GlPixelFormatDescTemplate gl_formats_template[] = { /* WINED3DFORMAT internal srgbInternal rtInternal format type - flags */ - {WINED3DFMT_UNKNOWN, 0, 0, 0, - 0, 0, - 0}, + flags + extension */ /* FourCC formats */ /* 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 @@ -192,208 +209,278 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = { * 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_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_UYVY, GL_RGB, GL_RGB, 0, GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_APPLE, - WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_FILTERING, + APPLE_YCBCR_422}, + {WINED3DFMT_YUY2, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, + WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_YUY2, GL_RGB, GL_RGB, 0, GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_REV_APPLE, - WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_FILTERING, + APPLE_YCBCR_422}, {WINED3DFMT_YV12, GL_ALPHA, GL_ALPHA, 0, GL_ALPHA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_DXT1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + EXT_TEXTURE_COMPRESSION_S3TC}, {WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + EXT_TEXTURE_COMPRESSION_S3TC}, {WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + EXT_TEXTURE_COMPRESSION_S3TC}, {WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + EXT_TEXTURE_COMPRESSION_S3TC}, {WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, - {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}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + EXT_TEXTURE_COMPRESSION_S3TC}, /* IEEE formats */ {WINED3DFMT_R32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0, GL_RED, GL_FLOAT, - WINED3DFMT_FLAG_RENDERTARGET}, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, + {WINED3DFMT_R32_FLOAT, GL_R32F, GL_R32F, 0, + GL_RED, GL_FLOAT, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_RG}, + {WINED3DFMT_R32G32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0, + GL_RGB, GL_FLOAT, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, {WINED3DFMT_R32G32_FLOAT, GL_RG32F, GL_RG32F, 0, GL_RG, GL_FLOAT, - WINED3DFMT_FLAG_RENDERTARGET}, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_RG}, {WINED3DFMT_R32G32B32A32_FLOAT, GL_RGBA32F_ARB, GL_RGBA32F_ARB, 0, GL_RGBA, GL_FLOAT, - WINED3DFMT_FLAG_RENDERTARGET}, - /* Hmm? */ - {WINED3DFMT_CxV8U8, 0, 0, 0, - 0, 0, - 0}, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, /* Float */ {WINED3DFMT_R16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0, - GL_RED, GL_HALF_FLOAT_ARB, - WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET}, + GL_RED, GL_HALF_FLOAT_ARB, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, + {WINED3DFMT_R16_FLOAT, GL_R16F, GL_R16F, 0, + GL_RED, GL_HALF_FLOAT_ARB, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_RG}, + {WINED3DFMT_R16G16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0, + GL_RGB, GL_HALF_FLOAT_ARB, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, {WINED3DFMT_R16G16_FLOAT, GL_RG16F, GL_RG16F, 0, - GL_RG, GL_HALF_FLOAT_ARB, - WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET}, + GL_RG, GL_HALF_FLOAT_ARB, + WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_RG}, {WINED3DFMT_R16G16B16A16_FLOAT, GL_RGBA16F_ARB, GL_RGBA16F_ARB, 0, - GL_RGBA, GL_HALF_FLOAT_ARB, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET}, + GL_RGBA, GL_HALF_FLOAT_ARB, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET, + ARB_TEXTURE_FLOAT}, /* Palettized formats */ - {WINED3DFMT_A8P8, 0, 0, 0, - 0, 0, - 0}, + {WINED3DFMT_P8, GL_RGBA, GL_RGBA, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + 0, + ARB_FRAGMENT_PROGRAM}, {WINED3DFMT_P8, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, - 0}, + 0, + EXT_PALETTED_TEXTURE}, /* Standard ARGB formats */ {WINED3DFMT_R8G8B8, GL_RGB8, GL_RGB8, 0, GL_BGR, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R3G3B2, GL_R3_G3_B2, GL_R3_G3_B2, 0, GL_RGB, GL_UNSIGNED_BYTE_3_3_2, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_A8_UNORM, GL_ALPHA8, GL_ALPHA8, 0, GL_ALPHA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING}, - {WINED3DFMT_A8R3G3B2, 0, 0, 0, - 0, 0, - 0}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R10G10B10A2_UNORM, 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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {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_R16G16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, + {WINED3DFMT_R16G16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, GL_RGBA16_EXT, GL_RGB, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {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_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R16G16B16A16_UNORM, GL_RGBA16_EXT, GL_RGBA16_EXT, 0, GL_RGBA, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET, + WINED3D_GL_EXT_NONE}, /* Luminance */ {WINED3DFMT_L8, GL_LUMINANCE8, GL_SLUMINANCE8_EXT, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_A8L8, GL_LUMINANCE8_ALPHA8, GL_SLUMINANCE8_ALPHA8_EXT, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_A4L4, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE4_ALPHA4, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - 0}, + 0, + WINED3D_GL_EXT_NONE}, /* Bump mapping stuff */ + {WINED3DFMT_R8G8_SNORM, GL_RGB8, GL_RGB8, 0, + GL_BGR, GL_UNSIGNED_BYTE, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R8G8_SNORM, GL_DSDT8_NV, GL_DSDT8_NV, 0, GL_DSDT_NV, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + NV_TEXTURE_SHADER}, + {WINED3DFMT_L6V5U5, GL_RGB5, GL_RGB5, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_L6V5U5, GL_DSDT8_MAG8_NV, GL_DSDT8_MAG8_NV, 0, GL_DSDT_MAG_NV, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + NV_TEXTURE_SHADER}, + {WINED3DFMT_X8L8V8U8, GL_RGB8, GL_RGB8, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {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_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + NV_TEXTURE_SHADER}, + {WINED3DFMT_R8G8B8A8_SNORM, GL_RGBA8, GL_RGBA8, 0, + GL_BGRA, GL_UNSIGNED_BYTE, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R8G8B8A8_SNORM, GL_SIGNED_RGBA8_NV, GL_SIGNED_RGBA8_NV, 0, GL_RGBA, GL_BYTE, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + NV_TEXTURE_SHADER}, + {WINED3DFMT_R16G16_SNORM, GL_RGB16_EXT, GL_RGB16_EXT, 0, + GL_BGR, GL_UNSIGNED_SHORT, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, {WINED3DFMT_R16G16_SNORM, GL_SIGNED_HILO16_NV, GL_SIGNED_HILO16_NV, 0, GL_HILO_NV, GL_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, - {WINED3DFMT_W11V11U10, 0, 0, 0, - 0, 0, - 0}, - {WINED3DFMT_A2W10V10U10, 0, 0, 0, - 0, 0, - 0}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + NV_TEXTURE_SHADER}, /* Depth stencil formats */ {WINED3DFMT_D16_LOCKABLE, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_DEPTH}, + WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, {WINED3DFMT_D32, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_DEPTH}, + WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, {WINED3DFMT_D15S1, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL}, + WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, + {WINED3DFMT_D15S1, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, + EXT_PACKED_DEPTH_STENCIL}, {WINED3DFMT_D24S8, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, + {WINED3DFMT_D24S8, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, + EXT_PACKED_DEPTH_STENCIL}, {WINED3DFMT_D24X8, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, {WINED3DFMT_D24X4S4, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL}, + WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, + {WINED3DFMT_D24X4S4, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, + GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, + EXT_PACKED_DEPTH_STENCIL}, {WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH}, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_TEXTURE}, {WINED3DFMT_L16, GL_LUMINANCE16_EXT, GL_LUMINANCE16_EXT, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, - WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING}, - {WINED3DFMT_D32F_LOCKABLE, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0, + WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, + WINED3D_GL_EXT_NONE}, + {WINED3DFMT_D32F_LOCKABLE, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, 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, 0, - 0}, - {WINED3DFMT_R16_UINT, 0, 0, 0, - 0, 0, - 0}, - {WINED3DFMT_R32_UINT, 0, 0, 0, - 0, 0, - 0}, - {WINED3DFMT_R16G16B16A16_SNORM, GL_COLOR_INDEX, GL_COLOR_INDEX, 0, - GL_COLOR_INDEX, GL_UNSIGNED_SHORT, - 0}, + WINED3DFMT_FLAG_DEPTH, + ARB_DEPTH_BUFFER_FLOAT}, + {WINED3DFMT_D24FS8, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, 0, + GL_DEPTH_STENCIL_EXT, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, + ARB_DEPTH_BUFFER_FLOAT}, /* Vendor-specific formats */ - {WINED3DFMT_ATI2N, 0, 0, 0, + {WINED3DFMT_ATI2N, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - 0}, - {WINED3DFMT_NVHU, 0, 0, 0, + 0, + ATI_TEXTURE_COMPRESSION_3DC}, + {WINED3DFMT_ATI2N, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - 0}, - {WINED3DFMT_NVHS, 0, 0, 0, - GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - 0} + 0, + EXT_TEXTURE_COMPRESSION_RGTC}, }; static inline int getFmtIdx(WINED3DFORMAT fmt) { @@ -413,7 +500,7 @@ static inline int getFmtIdx(WINED3DFORMAT fmt) { return -1; } -static BOOL init_format_base_info(WineD3D_GL_Info *gl_info) +static BOOL init_format_base_info(struct wined3d_gl_info *gl_info) { UINT format_count = sizeof(formats) / sizeof(*formats); UINT i; @@ -442,32 +529,216 @@ static BOOL init_format_base_info(WineD3D_GL_Info *gl_info) return TRUE; } +static BOOL init_format_compression_info(struct wined3d_gl_info *gl_info) +{ + unsigned int i; + + for (i = 0; i < (sizeof(format_compression_info) / sizeof(*format_compression_info)); ++i) + { + struct GlPixelFormatDesc *format_desc; + int fmt_idx = getFmtIdx(format_compression_info[i].format); + + if (fmt_idx == -1) + { + ERR("Format %s (%#x) not found.\n", + debug_d3dformat(format_compression_info[i].format), format_compression_info[i].format); + return FALSE; + } + + format_desc = &gl_info->gl_formats[fmt_idx]; + format_desc->block_width = format_compression_info[i].block_width; + format_desc->block_height = format_compression_info[i].block_height; + format_desc->block_byte_count = format_compression_info[i].block_byte_count; + format_desc->Flags |= WINED3DFMT_FLAG_COMPRESSED; + } + + return TRUE; +} + #define GLINFO_LOCATION (*gl_info) -static BOOL check_fbo_compat(const WineD3D_GL_Info *gl_info, GLint internal_format) +/* Context activation is done by the caller. */ +static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct GlPixelFormatDesc *format_desc) { - GLuint tex, fb; + /* 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. */ GLenum status; + GLuint tex; + + ENTER_GL(); while(glGetError()); + glDisable(GL_BLEND); + glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - GL_EXTCALL(glGenFramebuffersEXT(1, &fb)); - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb)); + glTexImage2D(GL_TEXTURE_2D, 0, format_desc->glInternal, 16, 16, 0, + format_desc->glFormat, format_desc->glType, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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"); - return status == GL_FRAMEBUFFER_COMPLETE_EXT; + if (status == GL_FRAMEBUFFER_COMPLETE_EXT) + { + TRACE("Format %s is supported as FBO color attachment\n", debug_d3dformat(format_desc->format)); + format_desc->Flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE; + format_desc->rtInternal = format_desc->glInternal; + } + else + { + if (!format_desc->rtInternal) + { + if (format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET) + { + FIXME("Format %s with rendertarget flag is not supported as FBO color attachment," + " and no fallback specified.\n", debug_d3dformat(format_desc->format)); + format_desc->Flags &= ~WINED3DFMT_FLAG_RENDERTARGET; + } + else + { + TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format_desc->format)); + } + format_desc->rtInternal = format_desc->glInternal; + } + else + { + TRACE("Format %s is not supported as FBO color attachment, trying rtInternal format as fallback.\n", + debug_d3dformat(format_desc->format)); + + while(glGetError()); + + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0)); + + glTexImage2D(GL_TEXTURE_2D, 0, format_desc->rtInternal, 16, 16, 0, + format_desc->glFormat, format_desc->glType, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0)); + + status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); + checkGLcall("Framebuffer format check"); + + if (status == GL_FRAMEBUFFER_COMPLETE_EXT) + { + TRACE("Format %s rtInternal format is supported as FBO color attachment\n", + debug_d3dformat(format_desc->format)); + } + else + { + FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n", + debug_d3dformat(format_desc->format)); + format_desc->Flags &= ~WINED3DFMT_FLAG_RENDERTARGET; + } + } + } + + if (status == GL_FRAMEBUFFER_COMPLETE_EXT && format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) + { + GLuint rb; + + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + GL_EXTCALL(glGenRenderbuffersEXT(1, &rb)); + GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb)); + GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, 16, 16)); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, rb)); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, rb)); + checkGLcall("RB attachment"); + } + + glEnable(GL_BLEND); + glClear(GL_COLOR_BUFFER_BIT); + if (glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION_EXT) + { + while(glGetError()); + TRACE("Format doesn't support post-pixelshader blending.\n"); + format_desc->Flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING; + } + + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, 0)); + GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, 0)); + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &rb)); + checkGLcall("RB cleanup"); + } + } + + glDeleteTextures(1, &tex); + + LEAVE_GL(); } -static BOOL init_format_texture_info(WineD3D_GL_Info *gl_info) +/* Context activation is done by the caller. */ +static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info) +{ + unsigned int i; + GLuint fbo; + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + ENTER_GL(); + + GL_EXTCALL(glGenFramebuffersEXT(1, &fbo)); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo)); + + LEAVE_GL(); + } + + for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i) + { + struct GlPixelFormatDesc *desc = &gl_info->gl_formats[i]; + + if (!desc->glInternal) continue; + + if (desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) + { + TRACE("Skipping format %s because it's a depth/stencil format.\n", + debug_d3dformat(desc->format)); + continue; + } + + if (desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + TRACE("Skipping format %s because it's a compressed format.\n", + debug_d3dformat(desc->format)); + continue; + } + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(desc->format)); + check_fbo_compat(gl_info, desc); + } + else + { + desc->rtInternal = desc->glInternal; + } + } + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + ENTER_GL(); + + GL_EXTCALL(glDeleteFramebuffersEXT(1, &fbo)); + + LEAVE_GL(); + } +} + +static BOOL init_format_texture_info(struct wined3d_gl_info *gl_info) { unsigned int i; @@ -483,65 +754,203 @@ static BOOL init_format_texture_info(WineD3D_GL_Info *gl_info) return FALSE; } + if (!GL_SUPPORT(gl_formats_template[i].extension)) continue; + desc = &gl_info->gl_formats[fmt_idx]; desc->glInternal = gl_formats_template[i].glInternal; desc->glGammaInternal = gl_formats_template[i].glGammaInternal; + desc->rtInternal = gl_formats_template[i].rtInternal; desc->glFormat = gl_formats_template[i].glFormat; desc->glType = gl_formats_template[i].glType; desc->color_fixup = COLOR_FIXUP_IDENTITY; desc->Flags |= gl_formats_template[i].Flags; - desc->heightscale = 1.0; - - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && gl_formats_template[i].rtInternal) - { - /* 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 */ - if (!check_fbo_compat(gl_info, gl_formats_template[i].glInternal)) - { - TRACE("Internal format of %s not supported as FBO target, using render target internal instead\n", - debug_d3dformat(gl_formats_template[i].fmt)); - desc->rtInternal = gl_formats_template[i].rtInternal; - } - else - { - TRACE("Format %s is supported as fbo target\n", debug_d3dformat(gl_formats_template[i].fmt)); - desc->rtInternal = gl_formats_template[i].glInternal; - } - } - else - { - desc->rtInternal = gl_formats_template[i].glInternal; - } + desc->heightscale = 1.0f; } return TRUE; } -static void apply_format_fixups(WineD3D_GL_Info *gl_info) +static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff) +{ + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; + return TRUE; +} + +/* A context is provided by the caller */ +static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal) +{ + GLuint tex, fbo, buffer; + const DWORD data[] = {0x00000000, 0xffffffff}; + DWORD readback[16 * 1]; + BOOL ret = FALSE; + + /* Render a filtered texture and see what happens. This is intended to detect the lack of + * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of + * falling back to software. If this changes in the future this code will get fooled and + * apps might hit the software path due to incorrectly advertised caps. + * + * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter + * disable fallback, if Apple or ATI ever change the driver behavior they will break more + * than Wine. The Linux binary <= r500 driver is not maintained any more anyway + */ + + ENTER_GL(); + while(glGetError()); + + glGenTextures(1, &buffer); + glBindTexture(GL_TEXTURE_2D, buffer); + memset(readback, 0x7e, sizeof(readback)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback); + 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_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glEnable(GL_TEXTURE_2D); + + GL_EXTCALL(glGenFramebuffersEXT(1, &fbo)); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo)); + GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, buffer, 0)); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + + glViewport(0, 0, 16, 1); + glDisable(GL_LIGHTING); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glClearColor(0, 1, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(0.0, 0.0); + glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0, 0.0); + glVertex2f(1.0f, -1.0f); + glTexCoord2f(0.0, 1.0); + glVertex2f(-1.0f, 1.0f); + glTexCoord2f(1.0, 1.0); + glVertex2f(1.0f, 1.0f); + glEnd(); + + glBindTexture(GL_TEXTURE_2D, buffer); + memset(readback, 0x7f, sizeof(readback)); + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback); + if(color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5) || + color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5)) + { + TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, asuming no filtering\n", + readback[6], readback[9]); + ret = FALSE; + } + else + { + TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n", + readback[6], readback[9]); + ret = TRUE; + } + + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + GL_EXTCALL(glDeleteFramebuffersEXT(1, &fbo)); + glDeleteTextures(1, &tex); + glDeleteTextures(1, &buffer); + + if(glGetError()) + { + FIXME("Error during filtering test for format %x, returning no filtering\n", internal); + ret = FALSE; + } + LEAVE_GL(); + return ret; +} + +static void init_format_filter_info(struct wined3d_gl_info *gl_info) +{ + unsigned int fmt_idx, i; + WINED3DFORMAT fmts16[] = { + WINED3DFMT_R16_FLOAT, + WINED3DFMT_R16G16_FLOAT, + WINED3DFMT_R16G16B16A16_FLOAT, + }; + BOOL filtered; + struct GlPixelFormatDesc *desc; + + if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) + { + WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n"); + if(gl_info->gl_vendor == VENDOR_NVIDIA && GL_SUPPORT(ARB_TEXTURE_FLOAT)) + { + TRACE("Nvidia card with texture_float support: Assuming float16 blending\n"); + filtered = TRUE; + } + else if(GL_LIMITS(glsl_varyings > 44)) + { + TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n"); + filtered = TRUE; + } + else + { + TRACE("Assuming no float16 blending\n"); + filtered = FALSE; + } + + if(filtered) + { + for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++) + { + fmt_idx = getFmtIdx(fmts16[i]); + gl_info->gl_formats[fmt_idx].Flags |= WINED3DFMT_FLAG_FILTERING; + } + } + return; + } + + for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++) + { + fmt_idx = getFmtIdx(fmts16[i]); + desc = &gl_info->gl_formats[fmt_idx]; + if(!desc->glInternal) continue; /* Not supported by GL */ + + filtered = check_filter(gl_info, gl_info->gl_formats[fmt_idx].glInternal); + if(filtered) + { + TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i])); + desc->Flags |= WINED3DFMT_FLAG_FILTERING; + } + else + { + TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i])); + } + } +} + +static void apply_format_fixups(struct wined3d_gl_info *gl_info) { int idx; idx = getFmtIdx(WINED3DFMT_R16_FLOAT); gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W); - /* When ARB_texture_rg is supported we only require 16-bit for R16F instead of 64-bit RGBA16F */ - if (GL_SUPPORT(ARB_TEXTURE_RG)) - { - gl_info->gl_formats[idx].glInternal = GL_R16F; - gl_info->gl_formats[idx].glGammaInternal = GL_R16F; - } idx = getFmtIdx(WINED3DFMT_R32_FLOAT); gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W); - /* When ARB_texture_rg is supported we only require 32-bit for R32F instead of 128-bit RGBA32F */ - if (GL_SUPPORT(ARB_TEXTURE_RG)) - { - gl_info->gl_formats[idx].glInternal = GL_R32F; - gl_info->gl_formats[idx].glGammaInternal = GL_R32F; - } idx = getFmtIdx(WINED3DFMT_R16G16_UNORM); gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( @@ -610,16 +1019,12 @@ static void apply_format_fixups(WineD3D_GL_Info *gl_info) if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { idx = getFmtIdx(WINED3DFMT_ATI2N); - gl_info->gl_formats[idx].glInternal = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; - gl_info->gl_formats[idx].glGammaInternal = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; gl_info->gl_formats[idx].color_fixup = create_color_fixup_desc( 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE); } else if (GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC)) { idx = getFmtIdx(WINED3DFMT_ATI2N); - gl_info->gl_formats[idx].glInternal = GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; - gl_info->gl_formats[idx].glGammaInternal = GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; gl_info->gl_formats[idx].color_fixup= create_color_fixup_desc( 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE); } @@ -627,22 +1032,14 @@ static void apply_format_fixups(WineD3D_GL_Info *gl_info) if (!GL_SUPPORT(APPLE_YCBCR_422)) { idx = getFmtIdx(WINED3DFMT_YUY2); - gl_info->gl_formats[idx].glInternal = GL_LUMINANCE_ALPHA; - gl_info->gl_formats[idx].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */ - gl_info->gl_formats[idx].glFormat = GL_LUMINANCE_ALPHA; - gl_info->gl_formats[idx].glType = GL_UNSIGNED_BYTE; gl_info->gl_formats[idx].color_fixup = create_yuv_fixup_desc(YUV_FIXUP_YUY2); idx = getFmtIdx(WINED3DFMT_UYVY); - gl_info->gl_formats[idx].glInternal = GL_LUMINANCE_ALPHA; - gl_info->gl_formats[idx].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */ - gl_info->gl_formats[idx].glFormat = GL_LUMINANCE_ALPHA; - gl_info->gl_formats[idx].glType = GL_UNSIGNED_BYTE; gl_info->gl_formats[idx].color_fixup = create_yuv_fixup_desc(YUV_FIXUP_UYVY); } idx = getFmtIdx(WINED3DFMT_YV12); - gl_info->gl_formats[idx].heightscale = 1.5; + gl_info->gl_formats[idx].heightscale = 1.5f; gl_info->gl_formats[idx].color_fixup = create_yuv_fixup_desc(YUV_FIXUP_YV12); if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)) @@ -663,7 +1060,7 @@ static void apply_format_fixups(WineD3D_GL_Info *gl_info) } } -static BOOL init_format_vertex_info(WineD3D_GL_Info *gl_info) +static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info) { unsigned int i; @@ -691,37 +1088,44 @@ static BOOL init_format_vertex_info(WineD3D_GL_Info *gl_info) return TRUE; } -BOOL initPixelFormatsNoGL(WineD3D_GL_Info *gl_info) -{ - return init_format_base_info(gl_info); -} - -BOOL initPixelFormats(WineD3D_GL_Info *gl_info) +BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) { if (!init_format_base_info(gl_info)) return FALSE; - if (!init_format_texture_info(gl_info)) + if (!init_format_compression_info(gl_info)) { HeapFree(GetProcessHeap(), 0, gl_info->gl_formats); return FALSE; } - if (!init_format_vertex_info(gl_info)) - { - HeapFree(GetProcessHeap(), 0, gl_info->gl_formats); - return FALSE; - } - - apply_format_fixups(gl_info); - return TRUE; } +/* Context activation is done by the caller. */ +BOOL initPixelFormats(struct wined3d_gl_info *gl_info) +{ + if (!init_format_base_info(gl_info)) return FALSE; + + if (!init_format_compression_info(gl_info)) goto fail; + if (!init_format_texture_info(gl_info)) goto fail; + if (!init_format_vertex_info(gl_info)) goto fail; + + apply_format_fixups(gl_info); + init_format_fbo_compat_info(gl_info); + init_format_filter_info(gl_info); + + return TRUE; + +fail: + HeapFree(GetProcessHeap(), 0, gl_info->gl_formats); + return FALSE; +} + #undef GLINFO_LOCATION #define GLINFO_LOCATION This->adapter->gl_info -const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, const WineD3D_GL_Info *gl_info) +const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, const struct wined3d_gl_info *gl_info) { int idx = getFmtIdx(fmt); @@ -907,9 +1311,12 @@ const char* debug_d3ddevicetype(WINED3DDEVTYPE devtype) { } } -const char* debug_d3dusage(DWORD usage) { - switch (usage & WINED3DUSAGE_MASK) { -#define WINED3DUSAGE_TO_STR(u) case u: return #u +const char *debug_d3dusage(DWORD usage) +{ + char buf[284]; + + buf[0] = '\0'; +#define WINED3DUSAGE_TO_STR(u) if (usage & u) { strcat(buf, " | "#u); usage &= ~u; } WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET); WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL); WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY); @@ -922,16 +1329,17 @@ const char* debug_d3dusage(DWORD usage) { WINED3DUSAGE_TO_STR(WINED3DUSAGE_AUTOGENMIPMAP); WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP); #undef WINED3DUSAGE_TO_STR - case 0: return "none"; - default: - FIXME("Unrecognized %u Usage!\n", usage); - return "unrecognized"; - } + if (usage) FIXME("Unrecognized usage flag(s) %#x\n", usage); + + return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0"; } -const char* debug_d3dusagequery(DWORD usagequery) { - switch (usagequery & WINED3DUSAGE_QUERY_MASK) { -#define WINED3DUSAGEQUERY_TO_STR(u) case u: return #u +const char *debug_d3dusagequery(DWORD usagequery) +{ + char buf[238]; + + buf[0] = '\0'; +#define WINED3DUSAGEQUERY_TO_STR(u) if (usagequery & u) { strcat(buf, " | "#u); usagequery &= ~u; } WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING); @@ -940,11 +1348,9 @@ const char* debug_d3dusagequery(DWORD usagequery) { WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP); #undef WINED3DUSAGEQUERY_TO_STR - case 0: return "none"; - default: - FIXME("Unrecognized %u Usage Query!\n", usagequery); - return "unrecognized"; - } + if (usagequery) FIXME("Unrecognized usage query flag(s) %#x\n", usagequery); + + return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0"; } const char* debug_d3ddeclmethod(WINED3DDECLMETHOD method) { @@ -1512,6 +1918,7 @@ BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP op, DWO } /* Setup this textures matrix according to the texture flags*/ +/* GL locking is done by the caller (state handler) */ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, WINED3DFORMAT vtx_fmt, BOOL ffp_proj_control) { @@ -1793,7 +2200,8 @@ 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? */ - if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) { + if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB) + { glTexCoord[0] = (float) Rect->left; glTexCoord[2] = (float) Rect->top; glTexCoord[1] = (float) Rect->right; @@ -1894,238 +2302,6 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4] } #undef GLINFO_LOCATION -/* Hash table functions */ - -struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function) -{ - struct hash_table_t *table; - unsigned int initial_size = 8; - - table = HeapAlloc(GetProcessHeap(), 0, sizeof(struct hash_table_t) + (initial_size * sizeof(struct list))); - if (!table) - { - ERR("Failed to allocate table, returning NULL.\n"); - return NULL; - } - - table->hash_function = hash_function; - table->compare_function = compare_function; - - table->grow_size = initial_size - (initial_size >> 2); - table->shrink_size = 0; - - table->buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, initial_size * sizeof(struct list)); - if (!table->buckets) - { - ERR("Failed to allocate table buckets, returning NULL.\n"); - HeapFree(GetProcessHeap(), 0, table); - return NULL; - } - table->bucket_count = initial_size; - - 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"); - HeapFree(GetProcessHeap(), 0, table->buckets); - HeapFree(GetProcessHeap(), 0, table); - return NULL; - } - table->entry_count = 0; - - list_init(&table->free_entries); - table->count = 0; - - return 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); - } - - HeapFree(GetProcessHeap(), 0, table->entries); - HeapFree(GetProcessHeap(), 0, table->buckets); - HeapFree(GetProcessHeap(), 0, table); -} - -void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context) -{ - unsigned int i = 0; - - for (i = 0; i < table->entry_count; ++i) - { - callback(table->entries[i].value, context); - } -} - -static inline struct hash_table_entry_t *hash_table_get_by_idx(const struct hash_table_t *table, const void *key, - unsigned int idx) -{ - struct hash_table_entry_t *entry; - - if (table->buckets[idx].next) - 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(struct hash_table_t *table, unsigned int new_bucket_count) -{ - unsigned int new_entry_count = 0; - 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; - - new_buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_bucket_count * sizeof(struct list)); - if (!new_buckets) - { - ERR("Failed to allocate new buckets, returning FALSE.\n"); - return FALSE; - } - - 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"); - HeapFree(GetProcessHeap(), 0, new_buckets); - return FALSE; - } - - for (i = 0; i < table->bucket_count; ++i) - { - if (table->buckets[i].next) - { - struct hash_table_entry_t *entry, *entry2; - - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &table->buckets[i], struct hash_table_entry_t, entry) - { - int j; - struct hash_table_entry_t *new_entry = new_entries + (new_entry_count++); - *new_entry = *entry; - - j = new_entry->hash & (new_bucket_count - 1); - - if (!new_buckets[j].next) list_init(&new_buckets[j]); - list_add_head(&new_buckets[j], &new_entry->entry); - } - } - } - - HeapFree(GetProcessHeap(), 0, table->buckets); - table->buckets = new_buckets; - - HeapFree(GetProcessHeap(), 0, table->entries); - table->entries = new_entries; - - table->entry_count = new_entry_count; - list_init(&table->free_entries); - - table->bucket_count = new_bucket_count; - table->grow_size = grow_size; - table->shrink_size = new_bucket_count > 8 ? new_bucket_count >> 2 : 0; - - return TRUE; -} - -void hash_table_put(struct hash_table_t *table, void *key, void *value) -{ - unsigned int idx; - unsigned int hash; - struct hash_table_entry_t *entry; - - hash = table->hash_function(key); - idx = hash & (table->bucket_count - 1); - entry = hash_table_get_by_idx(table, key, idx); - - if (entry) - { - HeapFree(GetProcessHeap(), 0, key); - entry->value = value; - - if (!value) - { - HeapFree(GetProcessHeap(), 0, entry->key); - entry->key = NULL; - - /* Remove the entry */ - list_remove(&entry->entry); - list_add_head(&table->free_entries, &entry->entry); - - --table->count; - - /* Shrink if necessary */ - if (table->count < table->shrink_size) { - if (!hash_table_resize(table, table->bucket_count >> 1)) - { - ERR("Failed to shrink the table...\n"); - } - } - } - - return; - } - - if (!value) return; - - /* Grow if necessary */ - if (table->count >= table->grow_size) - { - if (!hash_table_resize(table, table->bucket_count << 1)) - { - ERR("Failed to grow the table, returning.\n"); - return; - } - - idx = hash & (table->bucket_count - 1); - } - - /* Find an entry to insert */ - if (!list_empty(&table->free_entries)) - { - struct list *elem = list_head(&table->free_entries); - - list_remove(elem); - entry = LIST_ENTRY(elem, struct hash_table_entry_t, entry); - } else { - entry = table->entries + (table->entry_count++); - } - - /* Insert the entry */ - entry->key = key; - entry->value = value; - entry->hash = hash; - if (!table->buckets[idx].next) list_init(&table->buckets[idx]); - list_add_head(&table->buckets[idx], &entry->entry); - - ++table->count; -} - -void hash_table_remove(struct hash_table_t *table, void *key) -{ - hash_table_put(table, key, NULL); -} - -void *hash_table_get(const struct hash_table_t *table, const void *key) -{ - unsigned int idx; - 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_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings, BOOL ignore_textype) { #define ARG1 0x01 @@ -2163,6 +2339,7 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting unsigned int i; DWORD ttff; DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; for(i = 0; i < GL_LIMITS(texture_stages); i++) { IWineD3DBaseTextureImpl *texture; @@ -2216,8 +2393,7 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting carg2 = (args[cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : ARG_UNUSED; carg0 = (args[cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : ARG_UNUSED; - if(is_invalid_op(stateblock->wineD3DDevice, i, cop, - carg1, carg2, carg0)) { + if(is_invalid_op(device, i, cop, carg1, carg2, carg0)) { carg0 = ARG_UNUSED; carg2 = ARG_UNUSED; carg1 = WINED3DTA_CURRENT; @@ -2276,8 +2452,7 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting } } - if(is_invalid_op(stateblock->wineD3DDevice, i, aop, - aarg1, aarg2, aarg0)) { + if(is_invalid_op(device, i, aop, aarg1, aarg2, aarg0)) { aarg0 = ARG_UNUSED; aarg2 = ARG_UNUSED; aarg1 = WINED3DTA_CURRENT; @@ -2356,23 +2531,32 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting } else { settings->sRGB_write = 0; } + if(device->vs_clipping || !use_vs(stateblock)) { + /* No need to emulate clipplanes if GL supports native vertex shader clipping or if + * the fixed function vertex pipeline is used(which always supports clipplanes) + */ + settings->emul_clipplanes = 0; + } else { + settings->emul_clipplanes = 1; + } } #undef GLINFO_LOCATION -const struct ffp_frag_desc *find_ffp_frag_shader(const struct hash_table_t *fragment_shaders, +const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders, const struct ffp_frag_settings *settings) { - return hash_table_get(fragment_shaders, settings); + struct wine_rb_entry *entry = wine_rb_get(fragment_shaders, settings); + return entry ? WINE_RB_ENTRY_VALUE(entry, struct ffp_frag_desc, entry) : NULL; } -void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *desc) { - struct ffp_frag_settings *key = HeapAlloc(GetProcessHeap(), 0, sizeof(*key)); +void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) +{ /* Note that the key is the implementation independent part of the ffp_frag_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); + * whereas desc points to an extended structure with implementation specific parts. */ + if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1) + { + ERR("Failed to insert ffp frag shader.\n"); + } } /* Activates the texture dimension according to the bound D3D texture. @@ -2380,7 +2564,9 @@ void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *des * 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) { +/* GL locking is done by the caller (state handler) */ +void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ if(stateblock->textures[stage]) { switch (IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[stage])) { case GL_TEXTURE_2D: @@ -2453,7 +2639,9 @@ void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock } } -void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +/* GL locking is done by the caller (state handler) */ +void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context) +{ DWORD sampler = state - STATE_SAMPLER(0); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler]; @@ -2469,61 +2657,57 @@ void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } #undef GLINFO_LOCATION -unsigned int ffp_frag_program_key_hash(const void *key) +void *wined3d_rb_alloc(size_t size) { - const struct ffp_frag_settings *k = key; - unsigned int hash = 0, i; - const 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 = (const 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; + return HeapAlloc(GetProcessHeap(), 0, size); } -BOOL ffp_frag_program_key_compare(const void *keya, const void *keyb) +void *wined3d_rb_realloc(void *ptr, size_t size) { - const struct ffp_frag_settings *ka = keya; - const struct ffp_frag_settings *kb = keyb; - - return memcmp(ka, kb, sizeof(*ka)) == 0; + return HeapReAlloc(GetProcessHeap(), 0, ptr, size); } +void wined3d_rb_free(void *ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + +static int ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct ffp_frag_settings *ka = key; + const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings; + + return memcmp(ka, kb, sizeof(*ka)); +} + +const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + ffp_frag_program_key_compare, +}; + UINT wined3d_log2i(UINT32 x) { - static const BYTE l[] = + static const UINT l[] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + ~0U, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, }; UINT32 i; diff --git a/reactos/dll/directx/wine/wined3d/vertexshader.c b/reactos/dll/directx/wine/wined3d/vertexshader.c index 7dba4e37aaf..d24ecd6364a 100644 --- a/reactos/dll/directx/wine/wined3d/vertexshader.c +++ b/reactos/dll/directx/wine/wined3d/vertexshader.c @@ -71,6 +71,10 @@ static void vshader_set_limits(IWineD3DVertexShaderImpl *This) This->baseShader.limits.constant_float = min(256, GL_LIMITS(vshader_constantsF)); break; + case WINED3D_SHADER_VERSION(4,0): + FIXME("Using 3.0 limits for 4.0 shader\n"); + /* Fall through */ + case WINED3D_SHADER_VERSION(3,0): This->baseShader.limits.temporary = 32; This->baseShader.limits.constant_bool = 32; @@ -101,26 +105,6 @@ static void vshader_set_limits(IWineD3DVertexShaderImpl *This) } } -/* This is an internal function, - * used to create fake semantics for shaders - * that don't have them - d3d8 shaders where the declaration - * stores the register for each input - */ -static void vshader_set_input( - IWineD3DVertexShaderImpl* This, - unsigned int regnum, - BYTE usage, BYTE usage_idx) { - - This->semantics_in[regnum].usage = usage; - This->semantics_in[regnum].usage_idx = usage_idx; - This->semantics_in[regnum].reg.reg.type = WINED3DSPR_INPUT; - This->semantics_in[regnum].reg.reg.idx = regnum; - This->semantics_in[regnum].reg.write_mask = WINED3DSP_WRITEMASK_ALL; - This->semantics_in[regnum].reg.modifiers = 0; - This->semantics_in[regnum].reg.shift = 0; - This->semantics_in[regnum].reg.reg.rel_addr = NULL; -} - static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2) { if (usage_idx1 != usage_idx2) return FALSE; if (usage1 == usage2) return TRUE; @@ -130,19 +114,18 @@ static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_id return FALSE; } -BOOL vshader_get_input( - IWineD3DVertexShader* iface, - BYTE usage_req, BYTE usage_idx_req, - unsigned int* regnum) { +BOOL vshader_get_input(IWineD3DVertexShader* iface, BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum) +{ + IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; + WORD map = This->baseShader.reg_maps.input_registers; + unsigned int i; - IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface; - int i; + for (i = 0; map; map >>= 1, ++i) + { + if (!(map & 1)) continue; - for (i = 0; i < MAX_ATTRIBS; i++) { - if (!This->baseShader.reg_maps.attributes[i]) continue; - - if (match_usage(This->semantics_in[i].usage, - This->semantics_in[i].usage_idx, usage_req, usage_idx_req)) + if (match_usage(This->attributes[i].usage, + This->attributes[i].usage_idx, usage_req, usage_idx_req)) { *regnum = i; return TRUE; @@ -203,7 +186,7 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface static HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){ IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - + *parent = This->parent; IUnknown_AddRef(*parent); TRACE("(%p) : returning %p\n", This, *parent); @@ -249,6 +232,7 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; const struct wined3d_shader_frontend *fe; + unsigned int i; HRESULT hr; shader_reg_maps *reg_maps = &This->baseShader.reg_maps; @@ -280,16 +264,26 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader This->min_rel_offset = GL_LIMITS(vshader_constantsF); This->max_rel_offset = 0; hr = shader_get_registers_used((IWineD3DBaseShader*) This, fe, - reg_maps, This->semantics_in, This->semantics_out, pFunction, - GL_LIMITS(vshader_constantsF)); + reg_maps, This->attributes, NULL, This->output_signature, + pFunction, GL_LIMITS(vshader_constantsF)); if (hr != WINED3D_OK) return hr; + if (output_signature) + { + for (i = 0; i < output_signature->element_count; ++i) + { + struct wined3d_shader_signature_element *e = &output_signature->elements[i]; + reg_maps->output_registers |= 1 << e->register_idx; + This->output_signature[e->register_idx] = *e; + } + } + vshader_set_limits(This); - if(deviceImpl->vs_selected_mode == SHADER_ARB && - (GLINFO_LOCATION).arb_vs_offset_limit && - This->min_rel_offset <= This->max_rel_offset) { - + if (deviceImpl->vs_selected_mode == SHADER_ARB + && ((GLINFO_LOCATION).quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT) + && This->min_rel_offset <= This->max_rel_offset) + { if(This->max_rel_offset - This->min_rel_offset > 127) { FIXME("The difference between the minimum and maximum relative offset is > 127\n"); FIXME("Which this OpenGL implementation does not support. Try using GLSL\n"); @@ -312,19 +306,6 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader return WINED3D_OK; } -/* Preload semantics for d3d8 shaders */ -static void WINAPI IWineD3DVertexShaderImpl_FakeSemantics(IWineD3DVertexShader *iface, IWineD3DVertexDeclaration *vertex_declaration) { - IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface; - IWineD3DVertexDeclarationImpl* vdecl = (IWineD3DVertexDeclarationImpl*)vertex_declaration; - - unsigned int i; - for (i = 0; i < vdecl->element_count; ++i) - { - const struct wined3d_vertex_declaration_element *e = &vdecl->elements[i]; - vshader_set_input(This, e->output_slot, e->usage, e->usage_idx); - } -} - /* Set local constants for d3d8 shaders */ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertexShader *iface, UINT start_idx, const float *src_data, UINT count) { @@ -351,22 +332,6 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex return WINED3D_OK; } -static GLuint vertexshader_compile(IWineD3DVertexShaderImpl *This, const struct vs_compile_args *args) { - IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; - SHADER_BUFFER buffer; - GLuint ret; - - /* Generate the HW shader */ - TRACE("(%p) : Generating hardware program\n", This); - shader_buffer_init(&buffer); - This->cur_args = args; - ret = deviceImpl->shader_backend->shader_generate_vshader((IWineD3DVertexShader *)This, &buffer, args); - This->cur_args = NULL; - shader_buffer_free(&buffer); - - return ret; -} - const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl = { /*** IUnknown methods ***/ @@ -380,7 +345,6 @@ const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl = /*** IWineD3DVertexShader methods ***/ IWineD3DVertexShaderImpl_GetDevice, IWineD3DVertexShaderImpl_GetFunction, - IWineD3DVertexShaderImpl_FakeSemantics, IWIneD3DVertexShaderImpl_SetLocalConstantsF }; @@ -388,52 +352,3 @@ void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockIm args->fog_src = stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z; args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map; } - -static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, - const DWORD use_map) { - if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; - return stored->fog_src == new->fog_src; -} - -GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args) -{ - UINT i; - DWORD new_size = shader->shader_array_size; - struct vs_compiled_shader *new_array; - DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; - - /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), - * so a linear search is more performant than a hashmap or a binary search - * (cache coherency etc) - */ - for(i = 0; i < shader->num_gl_shaders; i++) { - if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) { - return shader->gl_shaders[i].prgId; - } - } - - TRACE("No matching GL shader found, compiling a new shader\n"); - - if(shader->shader_array_size == shader->num_gl_shaders) { - if (shader->num_gl_shaders) - { - new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2); - new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders, - new_size * sizeof(*shader->gl_shaders)); - } else { - new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders)); - new_size = 1; - } - - if(!new_array) { - ERR("Out of memory\n"); - return 0; - } - shader->gl_shaders = new_array; - shader->shader_array_size = new_size; - } - - shader->gl_shaders[shader->num_gl_shaders].args = *args; - shader->gl_shaders[shader->num_gl_shaders].prgId = vertexshader_compile(shader, args); - return shader->gl_shaders[shader->num_gl_shaders++].prgId; -} diff --git a/reactos/dll/directx/wine/wined3d/volume.c b/reactos/dll/directx/wine/wined3d/volume.c index 64d871b83ec..85e8f3ab831 100644 --- a/reactos/dll/directx/wine/wined3d/volume.c +++ b/reactos/dll/directx/wine/wined3d/volume.c @@ -26,10 +26,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info +/* Context activation is done by the caller. */ static void volume_bind_and_dirtify(IWineD3DVolume *iface) { IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; IWineD3DVolumeTexture *texture; - int active_sampler; + DWORD 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 @@ -52,7 +53,8 @@ static void volume_bind_and_dirtify(IWineD3DVolume *iface) { active_sampler = 0; } - if (active_sampler != -1) { + if (active_sampler != WINED3D_UNMAPPED_STAGE) + { IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler)); } @@ -196,14 +198,15 @@ static HRESULT WINAPI IWineD3DVolumeImpl_GetDesc(IWineD3DVolume *iface, WINED3DV IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; TRACE("(%p) : copying into %p\n", This, pDesc); - *(pDesc->Format) = This->resource.format_desc->format; - *(pDesc->Type) = This->resource.resourceType; - *(pDesc->Usage) = This->resource.usage; - *(pDesc->Pool) = This->resource.pool; - *(pDesc->Size) = This->resource.size; /* dx8 only */ - *(pDesc->Width) = This->currentDesc.Width; - *(pDesc->Height) = This->currentDesc.Height; - *(pDesc->Depth) = This->currentDesc.Depth; + pDesc->Format = This->resource.format_desc->format; + pDesc->Type = This->resource.resourceType; + pDesc->Usage = This->resource.usage; + pDesc->Pool = This->resource.pool; + pDesc->Size = This->resource.size; /* dx8 only */ + pDesc->Width = This->currentDesc.Width; + pDesc->Height = This->currentDesc.Height; + pDesc->Depth = This->currentDesc.Depth; + return WINED3D_OK; } @@ -300,6 +303,7 @@ static HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IWi return WINED3D_OK; } +/* Context activation is done by the caller. */ static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, int gl_level, BOOL srgb_mode) { IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; const struct GlPixelFormatDesc *glDesc = This->resource.format_desc; diff --git a/reactos/dll/directx/wine/wined3d/volumetexture.c b/reactos/dll/directx/wine/wined3d/volumetexture.c index 41a1160b1a0..134ff74398c 100644 --- a/reactos/dll/directx/wine/wined3d/volumetexture.c +++ b/reactos/dll/directx/wine/wined3d/volumetexture.c @@ -24,11 +24,177 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture); -#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + +#define GLINFO_LOCATION (*gl_info) + +static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) +{ + /* Override the IWineD3DResource Preload method. */ + IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + BOOL srgb_mode = This->baseTexture.is_srgb; + BOOL srgb_was_toggled = FALSE; + unsigned int i; + + TRACE("(%p) : About to load texture.\n", This); + + if (!device->isInDraw) + { + ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + } + else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) + { + srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; + srgb_was_toggled = This->baseTexture.is_srgb != srgb_mode; + This->baseTexture.is_srgb = srgb_mode; + } + + /* If the texture is marked dirty or the srgb sampler setting has changed + * since the last load then reload the volumes. */ + if (This->baseTexture.dirty) + { + for (i = 0; i < This->baseTexture.levels; ++i) + { + IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + } + } + else if (srgb_was_toggled) + { + for (i = 0; i < This->baseTexture.levels; ++i) + { + volume_add_dirty_box(This->volumes[i], NULL); + IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + } + } + else + { + TRACE("(%p) Texture not dirty, nothing to do.\n", iface); + } + + /* No longer dirty */ + This->baseTexture.dirty = FALSE; +} + +static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This, D3DCB_DESTROYVOLUMEFN volume_destroy_cb) +{ + unsigned int i; + + TRACE("(%p) : Cleaning up.\n", This); + + for (i = 0; i < This->baseTexture.levels; ++i) + { + IWineD3DVolume *volume = This->volumes[i]; + + if (volume) + { + /* Cleanup the container. */ + IWineD3DVolume_SetContainer(volume, NULL); + volume_destroy_cb(volume); + } + } + basetexture_cleanup((IWineD3DBaseTexture *)This); +} + +HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height, UINT depth, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) +{ + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info); + UINT tmp_w, tmp_h, tmp_d; + unsigned int i; + HRESULT hr; + + /* 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", texture); + return WINED3DERR_INVALIDCALL; + } + + if (!GL_SUPPORT(EXT_TEXTURE3D)) + { + WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); + return WINED3DERR_INVALIDCALL; + } + + /* Calculate levels for mip mapping. */ + if (usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + + levels = 1; + } + else if (!levels) + { + levels = wined3d_log2i(max(max(width, height), depth)) + 1; + TRACE("Calculated levels = %u.\n", levels); + } + + hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, + WINED3DRTYPE_VOLUMETEXTURE, device, 0, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize basetexture, returning %#x.\n", hr); + return hr; + } + + /* Is NP2 support for volumes needed? */ + texture->baseTexture.pow2Matrix[0] = 1.0f; + texture->baseTexture.pow2Matrix[5] = 1.0f; + texture->baseTexture.pow2Matrix[10] = 1.0f; + texture->baseTexture.pow2Matrix[15] = 1.0f; + + /* Generate all the surfaces. */ + tmp_w = width; + tmp_h = height; + tmp_d = depth; + + for (i = 0; i < texture->baseTexture.levels; ++i) + { + /* Create the volume. */ + hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent, + tmp_w, tmp_h, tmp_d, format, pool, usage, &texture->volumes[i]); + if (FAILED(hr)) + { + ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr); + texture->volumes[i] = NULL; + volumetexture_cleanup(texture, D3DCB_DefaultDestroyVolume); + return hr; + } + + /* Set its container to this texture. */ + IWineD3DVolume_SetContainer(texture->volumes[i], (IWineD3DBase *)texture); + + /* Calculate the next mipmap level. */ + tmp_w = max(1, tmp_w >> 1); + tmp_h = max(1, tmp_h >> 1); + tmp_d = max(1, tmp_d >> 1); + } + texture->baseTexture.internal_preload = volumetexture_internal_preload; + + return WINED3D_OK; +} + +#undef GLINFO_LOCATION /* ******************************************* IWineD3DTexture IUnknown parts follow ******************************************* */ + +#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + static HRESULT WINAPI IWineD3DVolumeTextureImpl_QueryInterface(IWineD3DVolumeTexture *iface, REFIID riid, LPVOID *ppobj) { IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; @@ -90,43 +256,6 @@ static DWORD WINAPI IWineD3DVolumeTextureImpl_GetPriority(IWineD3DVolumeTexture return resource_get_priority((IWineD3DResource *)iface); } -void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { - /* Overrider the IWineD3DResource Preload method */ - unsigned int i; - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL srgb_mode = This->baseTexture.is_srgb; - BOOL srgb_was_toggled = FALSE; - - TRACE("(%p) : About to load texture\n", This); - - if(!device->isInDraw) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { - srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; - srgb_was_toggled = This->baseTexture.is_srgb != srgb_mode; - This->baseTexture.is_srgb = srgb_mode; - } - - /* 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++) - IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); - } else if (srgb_was_toggled) { - for (i = 0; i < This->baseTexture.levels; i++) { - volume_add_dirty_box(This->volumes[i], NULL); - IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); - } - } else { - TRACE("(%p) Texture not dirty, nothing to do\n" , iface); - } - - /* No longer dirty */ - This->baseTexture.dirty = FALSE; - - return ; -} - static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *iface) { volumetexture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); } @@ -191,6 +320,7 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_GetDirty(IWineD3DVolumeTexture *ifa return basetexture_get_dirty((IWineD3DBaseTexture *)iface); } +/* Context activation is done by the caller. */ static HRESULT WINAPI IWineD3DVolumeTextureImpl_BindTexture(IWineD3DVolumeTexture *iface, BOOL srgb) { IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; BOOL dummy; @@ -211,30 +341,14 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *if 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]) { - IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - TRACE("(%p) : nothing to do, passing to base texture\n", This); - basetexture_apply_state_changes((IWineD3DBaseTexture *)iface, textureStates, samplerStates); -} - - /* ******************************************* IWineD3DVolumeTexture IWineD3DVolumeTexture parts follow ******************************************* */ static void WINAPI IWineD3DVolumeTextureImpl_Destroy(IWineD3DVolumeTexture *iface, D3DCB_DESTROYVOLUMEFN D3DCB_DestroyVolume) { IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - unsigned int i; - TRACE("(%p) : Cleaning up\n",This); - for (i = 0; i < This->baseTexture.levels; i++) { - if (This->volumes[i] != NULL) { - /* Cleanup the container */ - IWineD3DVolume_SetContainer(This->volumes[i], 0); - D3DCB_DestroyVolume(This->volumes[i]); - } - } - basetexture_cleanup((IWineD3DBaseTexture *)iface); + + volumetexture_cleanup(This, D3DCB_DestroyVolume); + HeapFree(GetProcessHeap(), 0, This); } @@ -330,7 +444,6 @@ const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl = IWineD3DVolumeTextureImpl_BindTexture, IWineD3DVolumeTextureImpl_GetTextureDimensions, IWineD3DVolumeTextureImpl_IsCondNP2, - IWineD3DVolumeTextureImpl_ApplyStateChanges, /* volume texture */ IWineD3DVolumeTextureImpl_Destroy, IWineD3DVolumeTextureImpl_GetLevelDesc, diff --git a/reactos/dll/directx/wine/wined3d/wined3d.spec b/reactos/dll/directx/wine/wined3d/wined3d.spec index 2f2677c1ce6..f65ee314dfa 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d.spec +++ b/reactos/dll/directx/wine/wined3d/wined3d.spec @@ -1,2 +1,4 @@ @ stdcall WineDirect3DCreate(long ptr) @ stdcall WineDirect3DCreateClipper(ptr) +@ stdcall wined3d_mutex_lock() +@ stdcall wined3d_mutex_unlock() diff --git a/reactos/dll/directx/wine/wined3d/wined3d_gl.h b/reactos/dll/directx/wine/wined3d/wined3d_gl.h index 1a9c9251899..9c85d576029 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_gl.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_gl.h @@ -1141,10 +1141,13 @@ 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 + * __stdcall calling convention. + * + * They are wgl functions and must not be called inside the gl lock, give them a + * name that makes this clear */ -void (__stdcall *glFinish) (); -void (__stdcall *glFlush) (); +void (__stdcall *wglFinish) (); +void (__stdcall *wglFlush) (); /* WGL functions */ HGLRC (WINAPI *pwglCreateContext)(HDC); @@ -1517,6 +1520,20 @@ BOOL (WINAPI *pwglShareLists)(HGLRC,HGLRC); #endif typedef void (WINE_GLAPI *PGLFNCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); +/* GL_ARB_depth_buffer_float */ +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 +#define GL_DEPTH_COMPONENT32F 0x8cac +#define GL_DEPTH32F_STENCIL8 0x8cad +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8dad +#endif + +/* GL_ARB_depth_clamp */ +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 +#define GL_DEPTH_CLAMP 0x864f +#endif + /* GL_ARB_depth_texture */ #ifndef GL_ARB_depth_texture #define GL_ARB_depth_texture 1 @@ -1897,6 +1914,15 @@ typedef void (WINE_GLAPI * PGLFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint sr #endif typedef void (WINE_GLAPI * PGLFNRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +/* GL_EXT_packed_depth_stencil */ +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 +#define GL_DEPTH_STENCIL_EXT 0x84f9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84fa +#define GL_DEPTH24_STENCIL8_EXT 0x88f0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88f1 +#endif + /* GL_EXT_secondary_color */ #ifndef GL_EXT_secondary_color #define GL_EXT_secondary_color 1 @@ -1935,6 +1961,17 @@ typedef void (WINE_GLAPI * PGLFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum inte #endif typedef void (WINE_GLAPI * PGLFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); typedef void (WINE_GLAPI * PGLFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); + +/* GL_EXT_provoking_vertex */ +#ifndef GL_EXT_provoking_vertex +#define GL_EXT_provoking_vertex 1 +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8e4d +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8e4e +#define GL_PROVOKING_VERTEX_EXT 0x8e4f +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTIONS_EXT 0x8e4c +#endif +typedef void (WINE_GLAPI * PGLFNGLPROVOKINGVERTEXEXTPROC)(GLenum mode); + /* GL_EXT_texture3D */ #ifndef GL_EXT_texture3D #define GL_EXT_texture3D 1 @@ -3080,6 +3117,13 @@ typedef void (WINE_GLAPI *PGLFNSETFRAGMENTSHADERCONSTANTATI) (GLuint dst, const #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #endif +/* GL_NV_vertex_program2_option */ +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#endif + /* GL_VERSION_2_0 */ #ifndef GL_VERSION_2_0 #define GL_VERSION_2_0 1 @@ -3302,6 +3346,18 @@ typedef enum _GL_Cards { CARD_ATI_RADEON_HD2600 = 0x9581, CARD_ATI_RADEON_HD2900 = 0x9400, CARD_ATI_RADEON_HD3200 = 0x9620, + CARD_ATI_RADEON_HD4350 = 0x954f, + CARD_ATI_RADEON_HD4550 = 0x9540, + CARD_ATI_RADEON_HD4600 = 0x9495, + CARD_ATI_RADEON_HD4650 = 0x9498, + CARD_ATI_RADEON_HD4670 = 0x9490, + CARD_ATI_RADEON_HD4700 = 0x944e, + CARD_ATI_RADEON_HD4770 = 0x94b3, + CARD_ATI_RADEON_HD4800 = 0x944c, /* picked one value between 9440,944c,9442,9460 */ + CARD_ATI_RADEON_HD4830 = 0x944c, + CARD_ATI_RADEON_HD4850 = 0x9442, + CARD_ATI_RADEON_HD4870 = 0x9440, + CARD_ATI_RADEON_HD4890 = 0x9460, CARD_NVIDIA_RIVA_128 = 0x0018, CARD_NVIDIA_RIVA_TNT = 0x0020, @@ -3342,39 +3398,21 @@ typedef enum _GL_Cards { CARD_INTEL_I915G = 0x2582, CARD_INTEL_I915GM = 0x2592, CARD_INTEL_I945GM = 0x27a2, /* Same as GMA 950?? */ + CARD_INTEL_X3100 = 0x2a02, /* found in macs. Same as GMA 965? */ } GL_Cards; #define WINE_DEFAULT_VIDMEM 64*1024*1024 -typedef enum _GL_VSVersion { - VS_VERSION_NOT_SUPPORTED = 0x0, - VS_VERSION_10 = 0x10, - VS_VERSION_11 = 0x11, - VS_VERSION_20 = 0x20, - VS_VERSION_30 = 0x30, - /*Force 32-bits*/ - VS_VERSION_FORCE_DWORD = 0x7FFFFFFF -} GL_VSVersion; - -typedef enum _GL_PSVersion { - PS_VERSION_NOT_SUPPORTED = 0x0, - PS_VERSION_10 = 0x10, - PS_VERSION_11 = 0x11, - PS_VERSION_12 = 0x12, - PS_VERSION_13 = 0x13, - PS_VERSION_14 = 0x14, - PS_VERSION_20 = 0x20, - PS_VERSION_30 = 0x30, - /*Force 32-bits*/ - PS_VERSION_FORCE_DWORD = 0x7FFFFFFF -} GL_PSVersion; - #define MAKEDWORD_VERSION(maj, min) ((maj & 0x0000FFFF) << 16) | (min & 0x0000FFFF) /* OpenGL Supported Extensions (ARB and EXT) */ typedef enum _GL_SupportedExt { + WINED3D_GL_EXT_NONE, /* ARB */ ARB_COLOR_BUFFER_FLOAT, + ARB_DEPTH_BUFFER_FLOAT, + ARB_DEPTH_CLAMP, + ARB_DEPTH_TEXTURE, ARB_DRAW_BUFFERS, ARB_FRAGMENT_PROGRAM, ARB_FRAGMENT_SHADER, @@ -3414,9 +3452,11 @@ typedef enum _GL_SupportedExt { EXT_FRAMEBUFFER_OBJECT, EXT_FRAMEBUFFER_BLIT, EXT_FRAMEBUFFER_MULTISAMPLE, + EXT_PACKED_DEPTH_STENCIL, EXT_PALETTED_TEXTURE, EXT_PIXEL_BUFFER_OBJECT, EXT_POINT_PARAMETERS, + EXT_PROVOKING_VERTEX, EXT_SECONDARY_COLOR, EXT_STENCIL_TWO_SIDE, EXT_STENCIL_WRAP, @@ -3449,7 +3489,9 @@ typedef enum _GL_SupportedExt { NV_VERTEX_PROGRAM, NV_VERTEX_PROGRAM1_1, NV_VERTEX_PROGRAM2, + NV_VERTEX_PROGRAM2_OPTION, NV_VERTEX_PROGRAM3, + NV_FRAGMENT_PROGRAM_OPTION, NV_FENCE, NV_DEPTH_CLAMP, NV_LIGHT_MAX_EXPONENT, @@ -3478,7 +3520,7 @@ typedef enum _GL_SupportedExt { WGL_ARB_PIXEL_FORMAT, WGL_WINE_PIXEL_FORMAT_PASSTHROUGH, - OPENGL_SUPPORTED_EXT_END + WINED3D_GL_EXT_COUNT, } GL_SupportedExt; @@ -3591,6 +3633,8 @@ typedef enum _GL_SupportedExt { /* GL_EXT_point_parameters */ \ USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC, glPointParameterfEXT, EXT_POINT_PARAMETERS, NULL )\ USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC, glPointParameterfvEXT, EXT_POINT_PARAMETERS, NULL )\ + /* GL_EXT_provoking_vertex */ \ + USE_GL_FUNC(PGLFNGLPROVOKINGVERTEXEXTPROC, glProvokingVertexEXT, EXT_PROVOKING_VERTEX, NULL)\ /* GL_EXT_secondary_color */ \ USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC, glSecondaryColor3ubEXT, EXT_SECONDARY_COLOR, NULL )\ USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBVEXTPROC, glSecondaryColor3ubvEXT, EXT_SECONDARY_COLOR, NULL )\ @@ -3906,77 +3950,61 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLSETPIXELFORMATWINE) (HDC hdc, int iPixelFor ****************************************************/ #define USE_GL_FUNC(type, pfn, ext, replace) type pfn; -typedef struct _WineD3D_GL_Info { - DWORD glx_version; - DWORD gl_version; +struct wined3d_gl_info +{ + GL_Vendors gl_vendor; + GL_Cards gl_card; + UINT vidmem; + DWORD driver_version; + DWORD driver_version_hipart; + const char *driver_description; - GL_Vendors gl_vendor; - GL_Cards gl_card; - UINT vidmem; - DWORD driver_version; - DWORD driver_version_hipart; - CHAR driver_description[255]; - CHAR gl_renderer[255]; - /** - * CAPS Constants - */ - UINT max_buffers; - UINT max_lights; - UINT max_textures; - UINT max_texture_stages; - UINT max_fragment_samplers; - UINT max_vertex_samplers; - UINT max_combined_samplers; - UINT max_sampler_stages; - UINT max_clipplanes; - UINT max_texture_size; - UINT max_texture3d_size; - float max_pointsize, max_pointsizemin; - UINT max_point_sprite_units; - UINT max_blends; - UINT max_anisotropy; - UINT max_glsl_varyings; - float max_shininess; + UINT max_buffers; + UINT max_lights; + UINT max_textures; + UINT max_texture_stages; + UINT max_fragment_samplers; + UINT max_vertex_samplers; + UINT max_combined_samplers; + UINT max_sampler_stages; + UINT max_clipplanes; + UINT max_texture_size; + UINT max_texture3d_size; + float max_pointsize, max_pointsizemin; + UINT max_point_sprite_units; + UINT max_blends; + UINT max_anisotropy; + UINT max_glsl_varyings; + float max_shininess; - unsigned max_vshader_constantsF; - unsigned max_pshader_constantsF; + unsigned int max_vshader_constantsF; + unsigned int max_pshader_constantsF; - unsigned vs_arb_constantsF; - unsigned vs_arb_max_instructions; - unsigned vs_arb_max_temps; - unsigned ps_arb_constantsF; - unsigned ps_arb_max_instructions; - unsigned ps_arb_max_temps; - unsigned vs_glsl_constantsF; - unsigned ps_glsl_constantsF; + unsigned int vs_arb_constantsF; + unsigned int vs_arb_max_instructions; + unsigned int vs_arb_max_temps; + unsigned int ps_arb_constantsF; + unsigned int ps_arb_max_local_constants; + unsigned int ps_arb_max_instructions; + unsigned int ps_arb_max_temps; + unsigned int vs_glsl_constantsF; + unsigned int ps_glsl_constantsF; - GL_PSVersion ps_arb_version; - GL_PSVersion ps_nv_version; + DWORD reserved_glsl_constants; - GL_VSVersion vs_arb_version; - GL_VSVersion vs_nv_version; - GL_VSVersion vs_ati_version; + DWORD quirks; - BOOL arb_vs_offset_limit; - BOOL set_texcoord_w; - DWORD reserved_glsl_constants; + BOOL supported[WINED3D_GL_EXT_COUNT]; - BOOL supported[OPENGL_SUPPORTED_EXT_END + 1]; + /* GL function pointers */ + GL_EXT_FUNCS_GEN + /* WGL function pointers */ + WGL_EXT_FUNCS_GEN - /** OpenGL EXT and ARB functions ptr */ - GL_EXT_FUNCS_GEN - /** OpenGL WGL functions ptr */ - WGL_EXT_FUNCS_GEN - - struct GlPixelFormatDesc *gl_formats; -} WineD3D_GL_Info; -#undef USE_GL_FUNC - -struct driver_quirk { - BOOL (*match)(const WineD3D_GL_Info *gl_info); - void (*apply)(WineD3D_GL_Info *gl_info); - const char *description; + struct GlPixelFormatDesc *gl_formats; }; +#undef USE_GL_FUNC + #endif /* __WINE_WINED3D_GL */ diff --git a/reactos/dll/directx/wine/wined3d/wined3d_main.c b/reactos/dll/directx/wine/wined3d/wined3d_main.c index 687fe893c05..bdb544a200f 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_main.c +++ b/reactos/dll/directx/wine/wined3d/wined3d_main.c @@ -32,17 +32,25 @@ int num_lock = 0; void (*CDECL wine_tsx11_lock_ptr)(void) = NULL; void (*CDECL wine_tsx11_unlock_ptr)(void) = NULL; +CRITICAL_SECTION wined3d_cs; +static CRITICAL_SECTION_DEBUG wined3d_cs_debug = +{ + 0, 0, &wined3d_cs, + {&wined3d_cs_debug.ProcessLocksList, + &wined3d_cs_debug.ProcessLocksList}, + 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs")} +}; +CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0}; /* When updating default value here, make sure to update winecfg as well, * where appropriate. */ -wined3d_settings_t wined3d_settings = +wined3d_settings_t wined3d_settings = { VS_HW, /* Hardware by default */ PS_HW, /* Hardware by default */ - VBO_HW, /* Hardware by default */ TRUE, /* Use of GLSL enabled by default */ - ORM_BACKBUFFER, /* Use the backbuffer to do offscreen rendering */ - RTL_AUTO, /* Automatically determine best locking method */ + ORM_FBO, /* Use FBOs to do offscreen rendering */ + RTL_READTEX, /* Default render target locking method */ PCI_VENDOR_NONE,/* PCI Vendor ID */ PCI_DEVICE_NONE,/* PCI Device ID */ 0, /* The default of memory is set in FillGLCaps */ @@ -97,6 +105,7 @@ static void CDECL wined3d_do_nothing(void) static BOOL wined3d_init(HINSTANCE hInstDLL) { + DWORD wined3d_context_tls_idx; HMODULE mod; char buffer[MAX_PATH+10]; DWORD size = sizeof(buffer); @@ -105,6 +114,15 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) DWORD len, tmpvalue; WNDCLASSA wc; + wined3d_context_tls_idx = TlsAlloc(); + if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES) + { + DWORD err = GetLastError(); + ERR("Failed to allocate context TLS index, err %#x.\n", err); + return FALSE; + } + context_set_tls_idx(wined3d_context_tls_idx); + /* We need our own window class for a fake window which we use to retrieve GL capabilities */ /* We might need CS_OWNDC in the future if we notice strange things on Windows. * Various articles/posts about OpenGL problems on Windows recommend this. */ @@ -117,11 +135,16 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; - wc.lpszClassName = "WineD3D_OpenGL"; + wc.lpszClassName = WINED3D_OPENGL_WINDOW_CLASS_NAME; - if (!RegisterClassA(&wc) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) + if (!RegisterClassA(&wc)) { ERR("Failed to register window class 'WineD3D_OpenGL'!\n"); + if (!TlsFree(wined3d_context_tls_idx)) + { + DWORD err = GetLastError(); + ERR("Failed to free context TLS index, err %#x.\n", err); + } return FALSE; } @@ -181,19 +204,6 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) wined3d_settings.ps_mode = PS_NONE; } } - if ( !get_config_key( hkey, appkey, "VertexBufferMode", buffer, size) ) - { - if (!strcmp(buffer,"none")) - { - TRACE("Disable Vertex Buffer Hardware support\n"); - wined3d_settings.vbo_mode = VBO_NONE; - } - else if (!strcmp(buffer,"hardware")) - { - TRACE("Allow Vertex Buffer Hardware support\n"); - wined3d_settings.vbo_mode = VBO_HW; - } - } if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) ) { if (!strcmp(buffer,"disabled")) @@ -237,16 +247,6 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) TRACE("Using glReadPixels for render target reading and textures for writing\n"); wined3d_settings.rendertargetlock_mode = RTL_READTEX; } - else if (!strcmp(buffer,"texdraw")) - { - TRACE("Using textures for render target reading and glDrawPixels for writing\n"); - wined3d_settings.rendertargetlock_mode = RTL_TEXDRAW; - } - else if (!strcmp(buffer,"textex")) - { - TRACE("Reading render targets via textures and writing via textures\n"); - wined3d_settings.rendertargetlock_mode = RTL_TEXTEX; - } } if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) ) { @@ -309,8 +309,6 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) TRACE("Allow HW vertex shaders\n"); if (wined3d_settings.ps_mode == PS_NONE) TRACE("Disable pixel shaders\n"); - if (wined3d_settings.vbo_mode == VBO_NONE) - TRACE("Disable Vertex Buffer Hardware support\n"); if (wined3d_settings.glslRequested) TRACE("If supported by your system, GL Shading Language will be used\n"); @@ -320,13 +318,32 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) return TRUE; } -static BOOL wined3d_destroy(void) +static BOOL wined3d_destroy(HINSTANCE hInstDLL) { + DWORD wined3d_context_tls_idx = context_get_tls_idx(); + + if (!TlsFree(wined3d_context_tls_idx)) + { + DWORD err = GetLastError(); + ERR("Failed to free context TLS index, err %#x.\n", err); + } + HeapFree(GetProcessHeap(), 0, wined3d_settings.logo); + UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL); return TRUE; } +void WINAPI wined3d_mutex_lock(void) +{ + EnterCriticalSection(&wined3d_cs); +} + +void WINAPI wined3d_mutex_unlock(void) +{ + LeaveCriticalSection(&wined3d_cs); +} + /* At process attach */ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) { @@ -338,7 +355,16 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) return wined3d_init(hInstDLL); case DLL_PROCESS_DETACH: - return wined3d_destroy(); + return wined3d_destroy(hInstDLL); + + case DLL_THREAD_DETACH: + { + if (!context_set_current(NULL)) + { + ERR("Failed to clear current context.\n"); + } + return TRUE; + } default: return TRUE; diff --git a/reactos/dll/directx/wine/wined3d/wined3d_private.h b/reactos/dll/directx/wine/wined3d/wined3d_private.h index 303fb7031f3..fefc54019c1 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private.h @@ -41,6 +41,13 @@ #include "wine/wined3d.h" #include "wined3d_gl.h" #include "wine/list.h" +#include "wine/rbtree.h" + +/* Driver quirks */ +#define WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT 0x00000001 +#define WINED3D_QUIRK_SET_TEXCOORD_W 0x00000002 +#define WINED3D_QUIRK_GLSL_CLIP_VARYING 0x00000004 +#define WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA 0x00000008 /* Texture format fixups */ @@ -126,38 +133,9 @@ static inline enum yuv_fixup get_yuv_fixup(struct color_fixup_desc fixup) return yuv_fixup; } -/* Hash table functions */ -typedef unsigned int (hash_function_t)(const void *key); -typedef BOOL (compare_function_t)(const void *keya, const void *keyb); - -#define ceilf(x) (float)ceil((double)x) - -struct hash_table_entry_t { - void *key; - void *value; - unsigned int hash; - struct list entry; -}; - -struct hash_table_t { - hash_function_t *hash_function; - compare_function_t *compare_function; - struct list *buckets; - unsigned int bucket_count; - 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; -}; - -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_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context); -void *hash_table_get(const struct hash_table_t *table, const 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); +void *wined3d_rb_alloc(size_t size); +void *wined3d_rb_realloc(void *ptr, size_t size); +void wined3d_rb_free(void *ptr); /* Device caps */ #define MAX_PALETTES 65536 @@ -198,13 +176,22 @@ struct min_lookup GLenum mip[WINED3DTEXF_LINEAR + 1]; }; -struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1]; -const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1]; -GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1]; -const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1]; +const struct min_lookup minMipLookup[WINED3DTEXF_LINEAR + 1]; +const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_LINEAR + 1]; +const struct min_lookup minMipLookup_noMip[WINED3DTEXF_LINEAR + 1]; +const GLenum magLookup[WINED3DTEXF_LINEAR + 1]; +const GLenum magLookup_noFilter[WINED3DTEXF_LINEAR + 1]; -extern const struct filter_lookup filter_lookup_nofilter; -extern struct filter_lookup filter_lookup; +static inline GLenum wined3d_gl_mag_filter(const GLenum mag_lookup[], WINED3DTEXTUREFILTERTYPE mag_filter) +{ + return mag_lookup[mag_filter]; +} + +static inline GLenum wined3d_gl_min_mip_filter(const struct min_lookup min_mip_lookup[], + WINED3DTEXTUREFILTERTYPE min_filter, WINED3DTEXTUREFILTERTYPE mip_filter) +{ + return min_mip_lookup[min_filter].mip[mip_filter]; +} /* float_16_to_32() and float_32_to_16() (see implementation in * surface_base.c) convert 16 bit floats in the FLOAT16 data type @@ -220,21 +207,43 @@ 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); + const float sgn = (s ? -1.0f : 1.0f); 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); + if(m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * pow(2, -14.0f) * ((float)m / 1024.0f); } else if(e < 31) { - return sgn * pow(2, (float) e-15.0) * (1.0 + ((float) m / 1024.0)); + return sgn * pow(2, (float)e - 15.0f) * (1.0f + ((float)m / 1024.0f)); } else { - if(m == 0) return sgn / 0.0; /* +INF / -INF */ - else return 0.0 / 0.0; /* NAN */ + if(m == 0) return sgn / 0.0f; /* +INF / -INF */ + else return 0.0f / 0.0f; /* NAN */ + } +} + +static inline float float_24_to_32(DWORD in) +{ + const float sgn = in & 0x800000 ? -1.0f : 1.0f; + const unsigned short e = (in & 0x780000) >> 19; + const unsigned short m = in & 0x7ffff; + + if (e == 0) + { + if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * pow(2, -6.0f) * ((float)m / 524288.0f); + } + else if (e < 15) + { + return sgn * pow(2, (float)e - 7.0f) * (1.0f + ((float)m / 524288.0f)); + } + else + { + if (m == 0) return sgn / 0.0f; /* +INF / -INF */ + else return 0.0f / 0.0f; /* NAN */ } } /** - * Settings + * Settings */ #define VS_NONE 0 #define VS_HW 1 @@ -259,11 +268,8 @@ static inline float float_16_to_32(const unsigned short *in) { #define SHADER_NONE 4 #define RTL_DISABLE -1 -#define RTL_AUTO 0 #define RTL_READDRAW 1 #define RTL_READTEX 2 -#define RTL_TEXDRAW 3 -#define RTL_TEXTEX 4 #define PCI_VENDOR_NONE 0xffff /* e.g. 0x8086 for Intel and 0x10de for Nvidia */ #define PCI_DEVICE_NONE 0xffff /* e.g. 0x14f for a Geforce6200 */ @@ -274,7 +280,6 @@ typedef struct wined3d_settings_s { /* vertex and pixel shader modes */ int vs_mode; int ps_mode; - int vbo_mode; /* Ideally, we don't want the user to have to request GLSL. If the hardware supports GLSL, we should use it. However, until it's fully implemented, we'll leave it as a registry setting for developers. */ @@ -325,6 +330,7 @@ typedef enum _WINED3DSHADER_PARAM_REGISTER_TYPE WINED3DSPR_LABEL = 18, WINED3DSPR_PREDICATE = 19, WINED3DSPR_IMMCONST, + WINED3DSPR_CONSTBUFFER, } WINED3DSHADER_PARAM_REGISTER_TYPE; enum wined3d_immconst_type @@ -506,12 +512,14 @@ typedef enum COMPARISON_TYPE #define MAX_LABELS 16 #define SHADER_PGMSIZE 65535 -typedef struct SHADER_BUFFER { - char* buffer; + +struct wined3d_shader_buffer +{ + char *buffer; unsigned int bsize; unsigned int lineNo; BOOL newline; -} SHADER_BUFFER; +}; enum WINED3D_SHADER_INSTRUCTION_HANDLER { @@ -620,28 +628,40 @@ struct wined3d_shader_version typedef struct shader_reg_maps { struct wined3d_shader_version shader_version; - char texcoord[MAX_REG_TEXCRD]; /* pixel < 3.0 */ - char temporary[MAX_REG_TEMP]; /* pixel, vertex */ - char address[MAX_REG_ADDR]; /* vertex */ - char packed_input[MAX_REG_INPUT]; /* pshader >= 3.0 */ - char packed_output[MAX_REG_OUTPUT]; /* vertex >= 3.0 */ - char attributes[MAX_ATTRIBS]; /* vertex */ - char labels[MAX_LABELS]; /* pixel, vertex */ + BYTE texcoord; /* MAX_REG_TEXCRD, 8 */ + BYTE address; /* MAX_REG_ADDR, 1 */ + WORD labels; /* MAX_LABELS, 16 */ + DWORD temporary; /* MAX_REG_TEMP, 32 */ DWORD *constf; /* pixel, vertex */ DWORD texcoord_mask[MAX_REG_TEXCRD]; /* vertex < 3.0 */ + WORD input_registers; /* max(MAX_REG_INPUT, MAX_ATTRIBS), 16 */ + WORD output_registers; /* MAX_REG_OUTPUT, 12 */ WORD integer_constants; /* MAX_CONST_I, 16 */ WORD boolean_constants; /* MAX_CONST_B, 16 */ + WORD local_int_consts; /* MAX_CONST_I, 16 */ + WORD local_bool_consts; /* MAX_CONST_B, 16 */ WINED3DSAMPLER_TEXTURE_TYPE sampler_type[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; - BOOL bumpmat[MAX_TEXTURES], luminanceparams[MAX_TEXTURES]; - char usesnrm, vpos, usesdsy, usestexldd; - char usesrelconstF; + BYTE bumpmat; /* MAX_TEXTURES, 8 */ + BYTE luminanceparams; /* MAX_TEXTURES, 8 */ + + WORD usesnrm : 1; + WORD vpos : 1; + WORD usesdsx : 1; + WORD usesdsy : 1; + WORD usestexldd : 1; + WORD usesmova : 1; + WORD usesfacing : 1; + WORD usesrelconstF : 1; + WORD fog : 1; + WORD usestexldl : 1; + WORD usesifc : 1; + WORD usescall : 1; + WORD padding : 4; /* Whether or not loops are used in this shader, and nesting depth */ unsigned loop_depth; - - /* Whether or not this shader uses fog */ - char fog; + unsigned highest_render_target; } shader_reg_maps; @@ -649,13 +669,15 @@ struct wined3d_shader_context { IWineD3DBaseShader *shader; const struct shader_reg_maps *reg_maps; - SHADER_BUFFER *buffer; + struct wined3d_shader_buffer *buffer; + void *backend_data; }; struct wined3d_shader_register { WINED3DSHADER_PARAM_REGISTER_TYPE type; UINT idx; + UINT array_idx; const struct wined3d_shader_src_param *rel_addr; enum wined3d_immconst_type immconst_type; DWORD immconst_data[4]; @@ -697,6 +719,19 @@ struct wined3d_shader_semantic struct wined3d_shader_dst_param reg; }; +struct wined3d_shader_attribute +{ + WINED3DDECLUSAGE usage; + UINT usage_idx; +}; + +struct wined3d_shader_loop_control +{ + unsigned int count; + unsigned int start; + int step; +}; + struct wined3d_shader_frontend { void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature); @@ -732,6 +767,8 @@ struct shader_caps { DWORD MaxPShaderInstructionsExecuted; DWORD MaxVertexShader30InstructionSlots; DWORD MaxPixelShader30InstructionSlots; + + BOOL VSClipping; }; enum tex_types @@ -752,11 +789,6 @@ enum vertexprocessing_mode { #define WINED3D_CONST_NUM_UNUSED ~0U -struct stb_const_desc { - unsigned char texunit; - UINT const_num; -}; - enum fogmode { FOG_OFF, FOG_LINEAR, @@ -790,24 +822,22 @@ struct vs_compile_args { WORD swizzle_map; /* MAX_ATTRIBS, 16 */ }; +struct wined3d_context; + typedef struct { - const SHADER_HANDLER *shader_instruction_handler_table; - void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS); + void (*shader_handle_instruction)(const struct wined3d_shader_instruction *); + void (*shader_select)(const struct wined3d_context *context, BOOL usePS, BOOL useVS); void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type); void (*shader_deselect_depth_blt)(IWineD3DDevice *iface); void (*shader_update_float_vertex_constants)(IWineD3DDevice *iface, UINT start, UINT count); void (*shader_update_float_pixel_constants)(IWineD3DDevice *iface, UINT start, UINT count); - void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); + void (*shader_load_constants)(const struct wined3d_context *context, char usePS, char useVS); void (*shader_load_np2fixup_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_destroy)(IWineD3DBaseShader *iface); HRESULT (*shader_alloc_private)(IWineD3DDevice *iface); void (*shader_free_private)(IWineD3DDevice *iface); BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface); - GLuint (*shader_generate_pshader)(IWineD3DPixelShader *iface, - SHADER_BUFFER *buffer, const struct ps_compile_args *args); - GLuint (*shader_generate_vshader)(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args); - void (*shader_get_caps)(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *caps); + void (*shader_get_caps)(WINED3DDEVTYPE devtype, const struct wined3d_gl_info *gl_info, struct shader_caps *caps); BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup); void (*shader_add_instruction_modifiers)(const struct wined3d_shader_instruction *ins); } shader_backend_t; @@ -870,17 +900,19 @@ extern int num_lock; /* Checking of API calls */ /* --------------------- */ #ifndef WINE_NO_DEBUG_MSGS -#define checkGLcall(A) \ -do { \ - GLint err = glGetError(); \ - if (err == GL_NO_ERROR) { \ - TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ - \ - } else do { \ - FIXME(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n", \ - debug_glerror(err), err, A, __FILE__, __LINE__); \ - err = glGetError(); \ - } while (err != GL_NO_ERROR); \ +#define checkGLcall(A) \ +do { \ + GLint err; \ + if(!__WINE_IS_DEBUG_ON(_FIXME, __wine_dbch___default)) break; \ + err = glGetError(); \ + if (err == GL_NO_ERROR) { \ + TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ + \ + } else do { \ + FIXME(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n", \ + debug_glerror(err), err, A, __FILE__, __LINE__); \ + err = glGetError(); \ + } while (err != GL_NO_ERROR); \ } while(0) #else #define checkGLcall(A) do {} while(0) @@ -910,10 +942,11 @@ do { \ } while(0) /* Trace vector and strided data information */ -#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w); -#define TRACE_STRIDED(si, name) TRACE( #name "=(data:%p, stride:%d, format:%#x, vbo %d, stream %u)\n", \ +#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w) +#define TRACE_STRIDED(si, name) do { if (si->use_map & (1 << name)) \ + TRACE( #name "=(data:%p, stride:%d, format:%#x, vbo %d, stream %u)\n", \ si->elements[name].data, si->elements[name].stride, si->elements[name].format_desc->format, \ - si->elements[name].buffer_object, si->elements[name].stream_idx); + si->elements[name].buffer_object, si->elements[name].stream_idx); } while(0) /* Defines used for optimizations */ @@ -937,8 +970,8 @@ extern const float identity[16]; /* Trace information per-vertex: (extremely high amount of trace) */ #if 0 /* NOTE: Must be 0 in cvs */ # define VTRACE(A) TRACE A -#else -# define VTRACE(A) +#else +# define VTRACE(A) #endif /* TODO: Confirm each of these works when wined3d move completed */ @@ -951,21 +984,21 @@ extern const float identity[16]; the file is deleted */ # if 1 /* NOTE: Must be 1 in cvs, as this is mostly more useful than a trace from program start */ # define SINGLE_FRAME_DEBUGGING -# endif +# endif /* The following, when enabled, lets you see the makeup of the frame, by drawprimitive calls. - It can only be enabled when FRAME_DEBUGGING is also enabled - The contents of the back buffer are written into /tmp/backbuffer_* after each primitive + It can only be enabled when FRAME_DEBUGGING is also enabled + The contents of the back buffer are written into /tmp/backbuffer_* after each primitive array is drawn. */ -# if 0 /* NOTE: Must be 0 in cvs, as this give a lot of ppm files when compiled in */ +# if 0 /* NOTE: Must be 0 in cvs, as this give a lot of ppm files when compiled in */ # define SHOW_FRAME_MAKEUP 1 -# endif +# endif /* The following, when enabled, lets you see the makeup of the all the textures used during each of the drawprimitive calls. It can only be enabled when SHOW_FRAME_MAKEUP is also enabled. - The contents of the textures assigned to each stage are written into + The contents of the textures assigned to each stage are written into /tmp/texture_*_.ppm after each primitive array is drawn. */ # if 0 /* NOTE: Must be 0 in cvs, as this give a lot of ppm files when compiled in */ # define SHOW_TEXTURE_MAKEUP 0 -# endif +# endif extern BOOL isOn; extern BOOL isDumpingFrames; extern LONG primCounter; @@ -1053,8 +1086,6 @@ extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT]; (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1) /* Routines and structures related to state management */ -typedef struct WineD3DContext WineD3DContext; -typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *ctx); #define STATE_RENDER(a) (a) #define STATE_IS_RENDER(a) ((a) >= STATE_RENDER(1) && (a) <= STATE_RENDER(WINEHIGHEST_RENDER_STATE)) @@ -1106,71 +1137,31 @@ typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, #define STATE_HIGHEST (STATE_FRONTFACE) -struct StateEntry -{ - DWORD representative; - APPLYSTATEFUNC apply; -}; - -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, const WineD3D_GL_Info *gl_info, struct fragment_caps *caps); - HRESULT (*alloc_private)(IWineD3DDevice *iface); - void (*free_private)(IWineD3DDevice *iface); - BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); - 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 */ -HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, - const 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, const struct GlPixelFormatDesc *format_desc, - GLenum textype, UINT width, UINT height); - void (*unset_shader)(IWineD3DDevice *iface); - BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); -}; - -extern const struct blit_shader ffp_blit; -extern const struct blit_shader arbfp_blit; - enum fogsource { FOGSOURCE_FFP, FOGSOURCE_VS, FOGSOURCE_COORD, }; -/* The new context manager that should deal with onscreen and offscreen rendering */ -struct WineD3DContext { +#define WINED3D_MAX_FBO_ENTRIES 64 + +struct wined3d_occlusion_query +{ + struct list entry; + GLuint id; + struct wined3d_context *context; +}; + +struct wined3d_event_query +{ + struct list entry; + GLuint id; + struct wined3d_context *context; +}; + +struct wined3d_context +{ + const struct wined3d_gl_info *gl_info; /* State dirtification * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices * 0...numDirtyEntries - 1. isStateDirty is a redundant copy of the dirtyArray. Technically only one of them would be needed, @@ -1182,9 +1173,11 @@ struct WineD3DContext { DWORD isStateDirty[STATE_HIGHEST/32 + 1]; /* Bitmap to find out quickly if a state is dirty */ IWineD3DSurface *surface; + IWineD3DSurface *current_rt; DWORD tid; /* Thread ID which owns this context at the moment */ /* Stores some information about the context state for optimization */ + WORD render_offscreen : 1; WORD draw_buffer_dirty : 1; WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */ WORD last_was_pshader : 1; @@ -1197,7 +1190,8 @@ struct WineD3DContext { WORD isPBuffer : 1; WORD fog_enabled : 1; WORD num_untracked_materials : 2; /* Max value 2 */ - WORD padding : 3; + WORD current : 1; + WORD destroyed : 1; BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */ BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */ DWORD numbered_array_mask; @@ -1216,17 +1210,93 @@ struct WineD3DContext { GLint aux_buffers; /* FBOs */ + UINT fbo_entry_count; struct list fbo_list; struct fbo_entry *current_fbo; GLuint src_fbo; GLuint dst_fbo; + GLuint fbo_read_binding; + GLuint fbo_draw_binding; + + /* Queries */ + GLuint *free_occlusion_queries; + UINT free_occlusion_query_size; + UINT free_occlusion_query_count; + struct list occlusion_queries; + + GLuint *free_event_queries; + UINT free_event_query_size; + UINT free_event_query_count; + struct list event_queries; /* Extension emulation */ GLint gl_fog_source; GLfloat fog_coord_value; GLfloat color[4], fogstart, fogend, fogcolor[4]; + GLuint dummy_arbfp_prog; }; +typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *ctx); + +struct StateEntry +{ + DWORD representative; + APPLYSTATEFUNC apply; +}; + +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, const struct wined3d_gl_info *gl_info, struct fragment_caps *caps); + HRESULT (*alloc_private)(IWineD3DDevice *iface); + void (*free_private)(IWineD3DDevice *iface); + BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); + 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 */ +HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, + const struct 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, const struct GlPixelFormatDesc *format_desc, + GLenum textype, UINT width, UINT height); + void (*unset_shader)(IWineD3DDevice *iface); + BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); +}; + +extern const struct blit_shader ffp_blit; +extern const struct blit_shader arbfp_blit; + typedef enum ContextUsage { CTXUSAGE_RESOURCELOAD = 1, /* Only loads textures: No State is applied */ CTXUSAGE_DRAWPRIM = 2, /* OpenGL states are set up for blitting DirectDraw surfaces */ @@ -1234,14 +1304,24 @@ typedef enum ContextUsage { CTXUSAGE_CLEAR = 4, /* Drawable and states are set up for clearing */ } ContextUsage; -void ActivateContext(IWineD3DDeviceImpl *device, IWineD3DSurface *target, ContextUsage usage); -WineD3DContext *getActiveContext(void); -WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms); -void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context); +struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage); +struct wined3d_context *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, + BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms); +void DestroyContext(IWineD3DDeviceImpl *This, struct wined3d_context *context); +void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query); +void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query); void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type); -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 context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo); +void context_attach_depth_stencil_fbo(struct wined3d_context *context, + GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer); +void context_attach_surface_fbo(const struct wined3d_context *context, + GLenum fbo_target, DWORD idx, IWineD3DSurface *surface); +void context_free_event_query(struct wined3d_event_query *query); +void context_free_occlusion_query(struct wined3d_occlusion_query *query); +struct wined3d_context *context_get_current(void); +DWORD context_get_tls_idx(void); +BOOL context_set_current(struct wined3d_context *ctx); +void context_set_tls_idx(DWORD idx); void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain); HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain); @@ -1300,7 +1380,7 @@ struct WineD3DAdapter UINT num; BOOL opengl; POINT monitorPoint; - WineD3D_GL_Info gl_info; + struct wined3d_gl_info gl_info; const char *driver; const char *description; WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ @@ -1311,10 +1391,10 @@ struct WineD3DAdapter unsigned int UsedTextureRam; }; -extern BOOL initPixelFormats(WineD3D_GL_Info *gl_info); -BOOL initPixelFormatsNoGL(WineD3D_GL_Info *gl_info); +extern BOOL initPixelFormats(struct wined3d_gl_info *gl_info); +BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info); extern long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram); -extern void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info); +extern void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info); /***************************************************************************** * High order patch management @@ -1371,21 +1451,23 @@ struct texture_stage_op struct ffp_frag_settings { struct texture_stage_op op[MAX_TEXTURES]; enum fogmode fog; - /* Use an int instead of a char to get dword alignment */ - unsigned int sRGB_write; + /* Use shorts instead of chars to get dword alignment */ + unsigned short sRGB_write; + unsigned short emul_clipplanes; }; struct ffp_frag_desc { + struct wine_rb_entry entry; struct ffp_frag_settings settings; }; +extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions; + void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings, BOOL ignore_textype); -const struct ffp_frag_desc *find_ffp_frag_shader(const struct hash_table_t *fragment_shaders, +const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders, const struct ffp_frag_settings *settings); -void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *desc); -BOOL ffp_frag_program_key_compare(const void *keya, const void *keyb); -unsigned int ffp_frag_program_key_hash(const void *key); +void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc); /***************************************************************************** * IWineD3D implementation structure @@ -1408,12 +1490,6 @@ extern const IWineD3DVtbl IWineD3D_Vtbl; BOOL InitAdapters(IWineD3DImpl *This); -/* TODO: setup some flags in the registry to enable, disable pbuffer support -(since it will break quite a few things until contexts are managed properly!) */ -extern BOOL pbuffer_support; -/* allocate one pbuffer per surface */ -extern BOOL pbuffer_per_surface; - /* A helper function that dumps a resource list */ void dumpResources(struct list *list); @@ -1460,13 +1536,13 @@ struct IWineD3DDeviceImpl unsigned int max_ffp_textures, max_ffp_texture_stages; DWORD d3d_vshader_constantF, d3d_pshader_constantF; /* Advertised d3d caps, not GL ones */ + DWORD vs_clipping; WORD view_ident : 1; /* true iff view matrix is identity */ WORD untransformed : 1; WORD vertexBlendUsed : 1; /* To avoid needless setting of the blend matrices */ WORD isRecordingState : 1; WORD isInDraw : 1; - WORD render_offscreen : 1; WORD bCursorVisible : 1; WORD haveHardwareCursor : 1; WORD d3d_initialized : 1; @@ -1474,7 +1550,7 @@ struct IWineD3DDeviceImpl WORD softwareVertexProcessing : 1; /* process vertex shaders using software or hardware */ WORD useDrawStridedSlow : 1; WORD instancedDraw : 1; - WORD padding : 3; + WORD padding : 4; BYTE fixed_function_usage_map; /* MAX_TEXTURES, 8 */ @@ -1503,10 +1579,6 @@ struct IWineD3DDeviceImpl IWineD3DSurface *auto_depth_stencil_buffer; IWineD3DSurface *stencilBufferTarget; - /* Caches to avoid unneeded context changes */ - IWineD3DSurface *lastActiveRenderTarget; - IWineD3DSwapChain *lastActiveSwapChain; - /* palettes texture management */ UINT NumberOfPalettes; PALETTEENTRY **palettes; @@ -1554,11 +1626,9 @@ struct IWineD3DDeviceImpl const WineDirect3DVertexStridedData *up_strided; /* Context management */ - WineD3DContext **contexts; /* Dynamic array containing pointers to context structures */ - WineD3DContext *activeContext; - DWORD lastThread; + struct wined3d_context **contexts; UINT numContexts; - WineD3DContext *pbufferContext; /* The context that has a pbuffer as drawable */ + struct wined3d_context *pbufferContext; /* The context that has a pbuffer as drawable */ DWORD pbufferWidth, pbufferHeight; /* Size of the buffer drawable */ /* High level patch management */ @@ -1570,6 +1640,8 @@ struct IWineD3DDeviceImpl extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl; +void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource); +void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource); void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, BOOL use_vshader, struct wined3d_stream_info *stream_info, BOOL *fixup); void device_stream_info_from_strided(IWineD3DDeviceImpl *This, @@ -1579,7 +1651,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa float Z, DWORD Stencil); void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This); void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state); -static inline BOOL isStateDirty(WineD3DContext *context, DWORD state) { +static inline BOOL isStateDirty(struct wined3d_context *context, DWORD state) +{ DWORD idx = state >> 5; BYTE shift = state & 0x1f; return context->isStateDirty[idx] & (1 << shift); @@ -1640,7 +1713,7 @@ HRESULT resource_get_parent(IWineD3DResource *iface, IUnknown **parent); DWORD resource_get_priority(IWineD3DResource *iface); HRESULT resource_get_private_data(IWineD3DResource *iface, REFGUID guid, void *data, DWORD *data_size); -HRESULT resource_init(struct IWineD3DResourceClass *resource, WINED3DRESOURCETYPE resource_type, +HRESULT resource_init(IWineD3DResource *iface, WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, WINED3DPOOL pool, IUnknown *parent); WINED3DRESOURCETYPE resource_get_type(IWineD3DResource *iface); @@ -1654,8 +1727,6 @@ HRESULT resource_set_private_data(IWineD3DResource *iface, REFGUID guid, /***************************************************************************** * IWineD3DBaseTexture D3D- > openGL state map lookups */ -#define WINED3DFUNC_NOTSUPPORTED -2 -#define WINED3DFUNC_UNIMPLEMENTED -1 typedef enum winetexturestates { WINED3DTEXSTA_ADDRESSU = 0, @@ -1704,9 +1775,6 @@ typedef struct IWineD3DBaseTextureClass void (*internal_preload)(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); } IWineD3DBaseTextureClass; -void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); -void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); -void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb); typedef struct IWineD3DBaseTextureImpl @@ -1728,15 +1796,13 @@ WINED3DTEXTUREFILTERTYPE basetexture_get_autogen_filter_type(IWineD3DBaseTexture BOOL basetexture_get_dirty(IWineD3DBaseTexture *iface); DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface); DWORD basetexture_get_lod(IWineD3DBaseTexture *iface); -void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage); +HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type, + IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct GlPixelFormatDesc *format_desc, + WINED3DPOOL pool, IUnknown *parent); HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE filter_type); BOOL basetexture_set_dirty(IWineD3DBaseTexture *iface, BOOL dirty); DWORD basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD new_lod); void basetexture_unload(IWineD3DBaseTexture *iface); -static inline void basetexture_setsrgbcache(IWineD3DBaseTexture *iface, BOOL srgb) { - IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - This->baseTexture.is_srgb = srgb; -} /***************************************************************************** * IWineD3DTexture implementation structure (extends IWineD3DBaseTextureImpl) @@ -1757,6 +1823,9 @@ typedef struct IWineD3DTextureImpl extern const IWineD3DTextureVtbl IWineD3DTexture_Vtbl; +HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent); + /***************************************************************************** * IWineD3DCubeTexture implementation structure (extends IWineD3DBaseTextureImpl) */ @@ -1773,6 +1842,9 @@ typedef struct IWineD3DCubeTextureImpl extern const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl; +HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent); + typedef struct _WINED3DVOLUMET_DESC { UINT Width; @@ -1819,6 +1891,9 @@ typedef struct IWineD3DVolumeTextureImpl extern const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl; +HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height, UINT depth, UINT levels, + IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent); + typedef struct _WINED3DSURFACET_DESC { WINED3DMULTISAMPLE_TYPE MultiSampleType; @@ -1889,21 +1964,23 @@ struct IWineD3DSurfaceImpl UINT pow2Height; /* 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); + void (*get_drawable_size)(struct wined3d_context *context, UINT *width, UINT *height); /* Oversized texture */ RECT glRect; /* PBO */ GLuint pbo; + GLuint texture_name; + GLuint texture_name_srgb; + GLint texture_level; + GLenum texture_target; RECT lockedRect; RECT dirtyRect; int lockCount; #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy */ - glDescriptor glDescription; - /* For GetDC */ wineD3DSurface_DIB dib; HDC hDC; @@ -1934,6 +2011,13 @@ struct IWineD3DSurfaceImpl extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl; extern const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl; +UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height); +void surface_gdi_cleanup(IWineD3DSurfaceImpl *This); +HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, + UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, + UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, + WINED3DPOOL pool, IUnknown *parent); + /* Predeclare the shared Surface functions */ HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj); ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface); @@ -1974,10 +2058,10 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DL void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb); const void *WINAPI IWineD3DBaseSurfaceImpl_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 get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height); +void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height); +void get_drawable_size_pbuffer(struct wined3d_context *context, UINT *width, UINT *height); +void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height); void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back); @@ -2060,6 +2144,9 @@ typedef enum { CONVERT_G16R16, CONVERT_R16G16F, CONVERT_R32G32F, + CONVERT_D15S1, + CONVERT_D24X4S4, + CONVERT_D24FS8, } 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); @@ -2276,7 +2363,7 @@ typedef struct IWineD3DQueryImpl { const IWineD3DQueryVtbl *lpVtbl; LONG ref; /* Note: Ref counting not required */ - + IUnknown *parent; /*TODO: replace with iface usage */ #if 0 @@ -2290,25 +2377,12 @@ typedef struct IWineD3DQueryImpl WINED3DQUERYTYPE type; /* TODO: Think about using a IUnknown instead of a void* */ void *extendedData; - - } IWineD3DQueryImpl; extern const IWineD3DQueryVtbl IWineD3DQuery_Vtbl; extern const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl; extern const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl; -/* Datastructures for IWineD3DQueryImpl.extendedData */ -typedef struct WineQueryOcclusionData { - GLuint queryId; - WineD3DContext *ctx; -} WineQueryOcclusionData; - -typedef struct WineQueryEventData { - GLuint fenceId; - WineD3DContext *ctx; -} WineQueryEventData; - /* IWineD3DBuffer */ /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other @@ -2357,7 +2431,7 @@ struct wined3d_buffer extern const IWineD3DBufferVtbl wined3d_buffer_vtbl; const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer_object); -const BYTE *buffer_get_sysmem(struct wined3d_buffer *This); +BYTE *buffer_get_sysmem(struct wined3d_buffer *This); /* IWineD3DRendertargetView */ struct wined3d_rendertarget_view @@ -2395,7 +2469,7 @@ typedef struct IWineD3DSwapChainImpl long prev_time, frames; /* Performance tracking */ unsigned int vSyncCounter; - WineD3DContext **context; /* Later a array for multithreading */ + struct wined3d_context **context; unsigned int num_contexts; HWND win_handle; @@ -2418,10 +2492,12 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetPresentParameters(IWineD3DSwapChain HRESULT WINAPI IWineD3DBaseSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp); HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp); -WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface); +struct wined3d_context *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface); + +#define DEFAULT_REFRESH_RATE 0 /***************************************************************************** - * Utility function prototypes + * Utility function prototypes */ /* Trace routines */ @@ -2453,19 +2529,18 @@ GLenum CompareFunc(DWORD func); 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 state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); -void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); -void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); -void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context); +void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); +void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context); void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect); -void surface_force_reload(IWineD3DSurface *iface); GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain); -void surface_load_ds_location(IWineD3DSurface *iface, DWORD location); +void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location); void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location); void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height); void surface_set_texture_name(IWineD3DSurface *iface, GLuint name, BOOL srgb_name); @@ -2500,8 +2575,8 @@ typedef struct SHADER_LIMITS { unsigned int label; } SHADER_LIMITS; -/** Keeps track of details for TEX_M#x# shader opcodes which need to - maintain state information between multiple codes */ +/* Keeps track of details for TEX_M#x# shader opcodes which need to + * maintain state information between multiple codes */ typedef struct SHADER_PARSE_STATE { unsigned int current_row; DWORD texcoord_w[2]; @@ -2513,12 +2588,9 @@ typedef struct SHADER_PARSE_STATE { #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, ...) PRINTF_ATTR(2,3); -int shader_vaddline(SHADER_BUFFER *buffer, const char *fmt, va_list args); +/* Base Shader utility functions. */ +int shader_addline(struct wined3d_shader_buffer *buffer, const char *fmt, ...) PRINTF_ATTR(2,3); +int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *fmt, va_list args); /* Vertex shader utility functions */ extern BOOL vshader_get_input( @@ -2566,19 +2638,23 @@ typedef struct IWineD3DBaseShaderImpl { IWineD3DBaseShaderClass baseShader; } IWineD3DBaseShaderImpl; -void shader_buffer_init(struct SHADER_BUFFER *buffer); -void shader_buffer_free(struct SHADER_BUFFER *buffer); +void shader_buffer_clear(struct wined3d_shader_buffer *buffer); +BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer); +void shader_buffer_free(struct wined3d_shader_buffer *buffer); void shader_cleanup(IWineD3DBaseShader *iface); void shader_dump_src_param(const struct wined3d_shader_src_param *param, const struct wined3d_shader_version *shader_version); void shader_dump_dst_param(const struct wined3d_shader_dst_param *param, const struct wined3d_shader_version *shader_version); -void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer, - const shader_reg_maps *reg_maps, const DWORD *pFunction); +unsigned int shader_find_free_input_register(const struct shader_reg_maps *reg_maps, unsigned int max); +void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffer *buffer, + const shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx); HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe, - struct shader_reg_maps *reg_maps, struct wined3d_shader_semantic *semantics_in, - struct wined3d_shader_semantic *semantics_out, const DWORD *byte_code, DWORD constf_size); + struct shader_reg_maps *reg_maps, struct wined3d_shader_attribute *attributes, + struct wined3d_shader_signature_element *input_signature, + struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size); void shader_init(struct IWineD3DBaseShaderClass *shader, IWineD3DDevice *device); +BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage); const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token); void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *pFunction); @@ -2647,14 +2723,8 @@ static inline BOOL shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD /***************************************************************************** * IDirect3DVertexShader implementation structures */ - -struct vs_compiled_shader { - struct vs_compile_args args; - GLuint prgId; -}; - typedef struct IWineD3DVertexShaderImpl { - /* IUnknown parts*/ + /* IUnknown parts */ const IWineD3DVertexShaderVtbl *lpVtbl; /* IWineD3DBaseShader */ @@ -2666,31 +2736,40 @@ typedef struct IWineD3DVertexShaderImpl { DWORD usage; /* The GL shader */ - struct vs_compiled_shader *gl_shaders; - UINT num_gl_shaders, shader_array_size; + void *backend_priv; /* Vertex shader input and output semantics */ - struct wined3d_shader_semantic semantics_in[MAX_ATTRIBS]; - struct wined3d_shader_semantic semantics_out[MAX_REG_OUTPUT]; + struct wined3d_shader_attribute attributes[MAX_ATTRIBS]; + struct wined3d_shader_signature_element output_signature[MAX_REG_OUTPUT]; UINT min_rel_offset, max_rel_offset; UINT rel_offset; UINT recompile_count; - - const struct vs_compile_args *cur_args; } IWineD3DVertexShaderImpl; extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl; void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args); -GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args); /***************************************************************************** * IDirect3DPixelShader implementation structure */ -struct ps_compiled_shader { - struct ps_compile_args args; - GLuint prgId; + +/* Using additional shader constants (uniforms in GLSL / program environment + * or local parameters in ARB) is costly: + * ARB only knows float4 parameters and GLSL compiler are not really smart + * when it comes to efficiently pack float2 uniforms, so no space is wasted + * (in fact most compilers map a float2 to a full float4 uniform). + * + * For NP2 texcoord fixup we only need 2 floats (width and height) for each + * 2D texture used in the shader. We therefore pack fixup info for 2 textures + * into a single shader constant (uniform / program parameter). + * + * This structure is shared between the GLSL and the ARB backend.*/ +struct ps_np2fixup_info { + unsigned char idx[MAX_FRAGMENT_SAMPLERS]; /* indices to the real constant */ + WORD active; /* bitfield indicating if we can apply the fixup */ + WORD num_consts; }; typedef struct IWineD3DPixelShaderImpl { @@ -2704,34 +2783,32 @@ typedef struct IWineD3DPixelShaderImpl { IUnknown *parent; /* Pixel shader input semantics */ - struct wined3d_shader_semantic semantics_in[MAX_REG_INPUT]; + struct wined3d_shader_signature_element input_signature[MAX_REG_INPUT]; DWORD input_reg_map[MAX_REG_INPUT]; BOOL input_reg_used[MAX_REG_INPUT]; - int declared_in_count; + unsigned int declared_in_count; /* The GL shader */ - struct ps_compiled_shader *gl_shaders; - UINT num_gl_shaders, shader_array_size; + void *backend_priv; /* Some information about the shader behavior */ - struct stb_const_desc bumpenvmatconst[MAX_TEXTURES]; - unsigned char numbumpenvmatconsts; - struct stb_const_desc luminanceconst[MAX_TEXTURES]; char vpos_uniform; - const struct ps_compile_args *cur_args; + BOOL color0_mov; + DWORD color0_reg; + } IWineD3DPixelShaderImpl; extern const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl; -GLuint find_gl_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args); +void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures); void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args); /* sRGB correction constants */ -static const float srgb_cmp = 0.0031308; -static const float srgb_mul_low = 12.92; -static const float srgb_pow = 0.41666; -static const float srgb_mul_high = 1.055; -static const float srgb_sub_high = 0.055; +static const float srgb_cmp = 0.0031308f; +static const float srgb_mul_low = 12.92f; +static const float srgb_pow = 0.41666f; +static const float srgb_mul_high = 1.055f; +static const float srgb_sub_high = 0.055f; /***************************************************************************** * IWineD3DPalette implementation structure @@ -2771,6 +2848,8 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth); #define WINED3DFMT_FLAG_STENCIL 0x8 #define WINED3DFMT_FLAG_RENDERTARGET 0x10 #define WINED3DFMT_FLAG_FOURCC 0x20 +#define WINED3DFMT_FLAG_FBO_ATTACHABLE 0x40 +#define WINED3DFMT_FLAG_COMPRESSED 0x80 struct GlPixelFormatDesc { @@ -2783,6 +2862,10 @@ struct GlPixelFormatDesc WORD depth_size; WORD stencil_size; + UINT block_width; + UINT block_height; + UINT block_byte_count; + enum wined3d_ffp_emit_idx emit_idx; GLint component_count; GLenum gl_vtx_type; @@ -2800,12 +2883,16 @@ struct GlPixelFormatDesc struct color_fixup_desc color_fixup; }; -const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, const WineD3D_GL_Info *gl_info); +const struct GlPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, const struct wined3d_gl_info *gl_info); static inline BOOL use_vs(IWineD3DStateBlockImpl *stateblock) { + /* Check stateblock->vertexDecl to allow this to be used from + * IWineD3DDeviceImpl_FindTexUnitMap(). This is safe because + * stateblock->vertexShader implies a vertex declaration instead of ddraw + * style strided data. */ return (stateblock->vertexShader - && !stateblock->wineD3DDevice->strided_streams.position_transformed + && !((IWineD3DVertexDeclarationImpl *)stateblock->vertexDecl)->position_transformed && stateblock->wineD3DDevice->vs_selected_mode != SHADER_NONE); } @@ -2817,4 +2904,8 @@ static inline BOOL use_ps(IWineD3DStateBlockImpl *stateblock) void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect, IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip); + +/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ +#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL" + #endif diff --git a/reactos/include/reactos/wine/wined3d.idl b/reactos/include/reactos/wine/wined3d.idl index 3845ded7bb9..ec204332fa1 100644 --- a/reactos/include/reactos/wine/wined3d.idl +++ b/reactos/include/reactos/wine/wined3d.idl @@ -1691,16 +1691,19 @@ typedef struct _WINED3DTRIPATCH_INFO typedef struct _WINED3DADAPTER_IDENTIFIER { - char *Driver; - char *Description; - char *DeviceName; - LARGE_INTEGER *DriverVersion; - DWORD *VendorId; - DWORD *DeviceId; - DWORD *SubSysId; - DWORD *Revision; - GUID *DeviceIdentifier; - DWORD *WHQLLevel; + char *driver; + UINT driver_size; + char *description; + UINT description_size; + char *device_name; + UINT device_name_size; + LARGE_INTEGER driver_version; + DWORD vendor_id; + DWORD device_id; + DWORD subsystem_id; + DWORD revision; + GUID device_identifier; + DWORD whql_level; } WINED3DADAPTER_IDENTIFIER; typedef struct _WINED3DPRESENT_PARAMETERS @@ -1724,27 +1727,27 @@ typedef struct _WINED3DPRESENT_PARAMETERS typedef struct _WINED3DSURFACE_DESC { - WINED3DFORMAT *Format; - WINED3DRESOURCETYPE *Type; - DWORD *Usage; - WINED3DPOOL *Pool; - UINT *Size; - WINED3DMULTISAMPLE_TYPE *MultiSampleType; - DWORD *MultiSampleQuality; - UINT *Width; - UINT *Height; + WINED3DFORMAT format; + WINED3DRESOURCETYPE resource_type; + DWORD usage; + WINED3DPOOL pool; + UINT size; + WINED3DMULTISAMPLE_TYPE multisample_type; + DWORD multisample_quality; + UINT width; + UINT height; } WINED3DSURFACE_DESC; typedef struct _WINED3DVOLUME_DESC { - WINED3DFORMAT *Format; - WINED3DRESOURCETYPE *Type; - DWORD *Usage; - WINED3DPOOL *Pool; - UINT *Size; - UINT *Width; - UINT *Height; - UINT *Depth; + WINED3DFORMAT Format; + WINED3DRESOURCETYPE Type; + DWORD Usage; + WINED3DPOOL Pool; + UINT Size; + UINT Width; + UINT Height; + UINT Depth; } WINED3DVOLUME_DESC; typedef struct _WINED3DCLIPSTATUS @@ -1883,13 +1886,6 @@ typedef struct _WINED3DBUFFER_DESC UINT Size; } WINED3DBUFFER_DESC; -typedef struct glDescriptor -{ - UINT textureName, srgbTextureName; - int level; - int /*GLenum*/ target; -} glDescriptor; - typedef struct WineDirect3DStridedData { WINED3DFORMAT format; /* Format of the data */ @@ -2529,9 +2525,6 @@ interface IWineD3DSurface : IWineD3DResource HRESULT SetContainer( [in] IWineD3DBase *container ); - void GetGlDesc( - [out] glDescriptor **desc - ); const void *GetData( ); HRESULT SetFormat( @@ -2616,10 +2609,6 @@ interface IWineD3DBaseTexture : IWineD3DResource ); BOOL IsCondNP2( ); - void ApplyStateChanges( - const DWORD texture_states[WINED3D_HIGHEST_TEXTURE_STATE + 1], - const DWORD sampler_states[WINED3D_HIGHEST_SAMPLER_STATE + 1] - ); } [ @@ -2872,9 +2861,6 @@ interface IWineD3DVertexShader : IWineD3DBaseShader [out] void *data, [in, out] UINT *data_size ); - void FakeSemantics( - [in] IWineD3DVertexDeclaration *vertex_declaration - ); HRESULT SetLocalConstantsF( [in] UINT start_idx, [in] const float *src_data, @@ -2939,7 +2925,6 @@ interface IWineD3DDevice : IWineD3DBase [in] BOOL discard, [in] UINT level, [out] IWineD3DSurface **surface, - [in] WINED3DRESOURCETYPE resource_type, [in] DWORD usage, [in] WINED3DPOOL pool, [in] WINED3DMULTISAMPLE_TYPE multisample_type, @@ -3015,8 +3000,8 @@ interface IWineD3DDevice : IWineD3DBase [in] DWORD fvf ); HRESULT CreateVertexShader( - [in] IWineD3DVertexDeclaration *declaration, [in] const DWORD *function, + [in] const struct wined3d_shader_signature *output_signature, [out] IWineD3DVertexShader **shader, [in] IUnknown *parent ); @@ -3475,9 +3460,6 @@ interface IWineD3DDevice : IWineD3DBase [in] UINT swapchain_idx, [in] IWineD3DSurface *dst_surface ); - void ResourceReleased( - [in] IWineD3DResource *resource - ); HRESULT EnumResources( [in] D3DCB_ENUMRESOURCES callback, [in] void *data @@ -3486,3 +3468,5 @@ interface IWineD3DDevice : IWineD3DBase IWineD3D *WineDirect3DCreate(UINT dxVersion, IUnknown *parent); IWineD3DClipper *WineDirect3DCreateClipper(IUnknown *parent); +void wined3d_mutex_lock(void); +void wined3d_mutex_unlock(void);