diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 3f9b7182f94..0db94d4d041 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -518,6 +518,10 @@ struct IDirect3DVolume8Impl D3DRESOURCETYPE ResourceType; void *Container; + D3DVOLUME_DESC myDesc; + BYTE *allocatedMemory; + UINT textureName; + UINT bytesPerPixel; }; @@ -797,6 +801,17 @@ struct IDirect3DVolumeTexture8Impl /* IDirect3DVolumeTexture8 fields */ IDirect3DDevice8Impl *Device; D3DRESOURCETYPE ResourceType; + UINT width; + UINT height; + UINT depth; + UINT levels; + DWORD usage; + D3DFORMAT format; + + IDirect3DDevice8Impl *device; + IDirect3DVolume8Impl *volumes[MAX_LEVELS]; + BOOL Dirty; + }; /* IUnknown: */ diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 240f935d632..dcc1e24ce44 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -30,7 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); /* CreateVertexShader can return > 0xFFFF */ -#define VS_HIGHESTFIXEDFXF 0xFFFF +#define VS_HIGHESTFIXEDFXF 0xF0000000 /* Used for CreateStateBlock */ #define NUM_SAVEDPIXELSTATES_R 38 @@ -293,6 +293,18 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t); glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t); break; + + case D3DRTYPE_VOLUMETEXTURE: + s = *(float *)curPos; + curPos = curPos + sizeof(float); + t = *(float *)curPos; + curPos = curPos + sizeof(float); + r = *(float *)curPos; + curPos = curPos + sizeof(float); + TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r); + glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r); + break; + default: r=0;q=0; /* Avoid compiler warnings, need these vars later for other textures */ FIXME("Unhandled texture type\n"); @@ -676,15 +688,83 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UIN HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) { IDirect3DVolumeTexture8Impl *object; + int i; + UINT tmpW; + UINT tmpH; + UINT tmpD; + ICOM_THIS(IDirect3DDevice8Impl,iface); /* Allocate the storage for it */ + TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Depth, Levels, Usage, Format, Pool); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl)); object->lpVtbl = &Direct3DVolumeTexture8_Vtbl; - object->ref = 1; - object->Device = This; object->ResourceType = D3DRTYPE_VOLUMETEXTURE; - TRACE("(%p) : Iface@%p\n", This, object); + object->ref = 1; + + + object->width = Width; + object->height = Height; + object->depth = Depth; + object->levels = Levels; + object->usage = Usage; + object->format = Format; + object->device = This; + + /* Calculate levels for mip mapping */ + if (Levels == 0) { + object->levels++; + tmpW = Width; + tmpH = Height; + tmpD = Depth; + while (tmpW > 1 && tmpH > 1 && tmpD > 1) { + tmpW = max(1,tmpW / 2); + tmpH = max(1, tmpH / 2); + tmpD = max(1, tmpD / 2); + object->levels++; + } + TRACE("Calculated levels = %d\n", object->levels); + } + + /* Generate all the surfaces */ + tmpW = Width; + tmpH = Height; + tmpD = Depth; + + /*for (i=0; ilevels; i++) { */ + i=0; + { + IDirect3DVolume8Impl *volume; + + /* Create the volume - No entry point for this seperately?? */ + volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl)); + object->volumes[i] = (IDirect3DVolume8Impl *) volume; + + volume->lpVtbl = &Direct3DVolume8_Vtbl; + volume->Device = This; + volume->ResourceType = D3DRTYPE_VOLUME; + volume->Container = object; + volume->ref = 1; + + volume->myDesc.Width = Width; + volume->myDesc.Height= Height; + volume->myDesc.Depth = Depth; + volume->myDesc.Format= Format; + volume->myDesc.Type = D3DRTYPE_VOLUME; + volume->myDesc.Pool = Pool; + volume->myDesc.Usage = Usage; + volume->bytesPerPixel = bytesPerPixel(Format); + volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth; + volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size); + + TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format, + volume, volume->allocatedMemory, volume->myDesc.Size); + + tmpW = max(1,tmpW / 2); + tmpH = max(1, tmpH / 2); + tmpD = max(1, tmpD / 2); + } + *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8)object; return D3D_OK; } @@ -2292,8 +2372,80 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); } + + } else if (textureType == D3DRTYPE_VOLUMETEXTURE) { + IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture; + int i; + float col[4]; + + /* Standard 3D (volume) texture */ + TRACE("Standard 3d texture\n"); +/* for (i=0; ilevels; i++) { */ + i=0; + { + + if (pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) { + glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName); + checkGLcall("glBindTexture"); + TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName); + } else { + + if (pTexture2->volumes[i]->textureName == 0) { + glGenTextures(1, &pTexture2->volumes[i]->textureName); + checkGLcall("glGenTextures"); + TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName); + } + + glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName); + checkGLcall("glBindTexture"); + + TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n", + GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width, + pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth, + 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format), + pTexture2->volumes[i]->allocatedMemory); + glTexImage3D(GL_TEXTURE_3D, i, + fmt2glintFmt(pTexture2->format), + pTexture2->volumes[i]->myDesc.Width, + pTexture2->volumes[i]->myDesc.Height, + pTexture2->volumes[i]->myDesc.Depth, + 0, + fmt2glFmt(pTexture2->format), + fmt2glType(pTexture2->format), + pTexture2->volumes[i]->allocatedMemory + ); + checkGLcall("glTexImage3D"); + + /* + * The following enable things to work but I dont think + * they all go here - FIXME! @@@ + */ + glTexParameterf( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + + + glEnable(GL_TEXTURE_3D); + checkGLcall("glEnable"); + + pTexture2->Dirty = FALSE; + } + + /* Note the D3DRS value applies to all textures, but GL has one + per texture, so apply it now ready to be used! */ + col[0] = ((This->StateBlock.renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0; + col[1] = ((This->StateBlock.renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0; + col[2] = ((This->StateBlock.renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0; + col[3] = ((This->StateBlock.renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); + checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); + + } + } else { - FIXME("(%p) : stub\n", This); + FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType); } } return D3D_OK; @@ -2309,6 +2461,8 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 ifa HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) { ICOM_THIS(IDirect3DDevice8Impl,iface); + /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */ + TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE; @@ -2329,7 +2483,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa switch (Type) { case D3DTSS_MINFILTER : - if (Value == D3DTEXF_POINT) { + if (Value == D3DTEXF_POINT) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, GL_NEAREST"); } else if (Value == D3DTEXF_LINEAR) { diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index 054c0ecf52e..d1da9bff049 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -319,7 +319,7 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps (LPDIRECT3D8 iface, pCaps->DestBlendCaps = 0; pCaps->AlphaCmpCaps = 0; pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_COLORGOURAUDRGB ; - pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_POW2; + pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_VOLUMEMAP; pCaps->TextureFilterCaps = 0; pCaps->CubeTextureFilterCaps = 0; pCaps->VolumeTextureFilterCaps = 0; diff --git a/dlls/d3d8/volume.c b/dlls/d3d8/volume.c index d9e5cabdd32..e0d0dfca86b 100644 --- a/dlls/d3d8/volume.c +++ b/dlls/d3d8/volume.c @@ -54,8 +54,10 @@ ULONG WINAPI IDirect3DVolume8Impl_Release(LPDIRECT3DVOLUME8 iface) { ICOM_THIS(IDirect3DVolume8Impl,iface); ULONG ref = --This->ref; TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) + if (ref == 0) { + HeapFree(GetProcessHeap(), 0, This->allocatedMemory); HeapFree(GetProcessHeap(), 0, This); + } return ref; } @@ -64,6 +66,11 @@ HRESULT WINAPI IDirect3DVolume8Impl_GetDevice(LPDIRECT3DVOLUME8 iface, IDirect3D ICOM_THIS(IDirect3DVolume8Impl,iface); TRACE("(%p) : returning %p\n", This, This->Device); *ppDevice = (LPDIRECT3DDEVICE8) This->Device; + + /* Note Calling this method will increase the internal reference count + on the IDirect3DDevice8 interface. */ + IDirect3DDevice8Impl_AddRef(*ppDevice); + return D3D_OK; } HRESULT WINAPI IDirect3DVolume8Impl_SetPrivateData(LPDIRECT3DVOLUME8 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { @@ -78,6 +85,7 @@ HRESULT WINAPI IDirect3DVolume8Impl_FreePrivateData(LPDIRECT3DVOLUME8 iface, REF ICOM_THIS(IDirect3DVolume8Impl,iface); FIXME("(%p) : stub\n", This); return D3D_OK; } + HRESULT WINAPI IDirect3DVolume8Impl_GetContainer(LPDIRECT3DVOLUME8 iface, REFIID riid, void** ppContainer) { ICOM_THIS(IDirect3DVolume8Impl,iface); TRACE("(%p) : returning %p\n", This, This->Container); @@ -86,15 +94,52 @@ HRESULT WINAPI IDirect3DVolume8Impl_GetContainer(LPDIRECT3DVOLUME8 iface, REFIID } HRESULT WINAPI IDirect3DVolume8Impl_GetDesc(LPDIRECT3DVOLUME8 iface, D3DVOLUME_DESC* pDesc) { ICOM_THIS(IDirect3DVolume8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + TRACE("(%p) : copying into %p\n", This, pDesc); + memcpy(pDesc, &This->myDesc, sizeof(D3DVOLUME_DESC)); + return D3D_OK; } HRESULT WINAPI IDirect3DVolume8Impl_LockBox(LPDIRECT3DVOLUME8 iface, D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox, DWORD Flags) { ICOM_THIS(IDirect3DVolume8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + FIXME("(%p) : pBox=%p stub\n", This, pBox); + + /* fixme: should we really lock as such? */ + TRACE("(%p) : box=%p, output pbox=%p, allMem=%p\n", This, pBox, pLockedVolume, This->allocatedMemory); + + pLockedVolume->RowPitch = This->bytesPerPixel * This->myDesc.Width; /* Bytes / row */ + pLockedVolume->SlicePitch = This->bytesPerPixel * This->myDesc.Width * This->myDesc.Height; /* Bytes / slice */ + if (!pBox) { + TRACE("No box supplied - all is ok\n"); + pLockedVolume->pBits = This->allocatedMemory; + } else { + TRACE("Lock Box (%p) = l %d, t %d, r %d, b %d, fr %d, ba %d\n", pBox, pBox->Left, pBox->Top, + pBox->Right, pBox->Bottom, pBox->Front, pBox->Back); + pLockedVolume->pBits = This->allocatedMemory + + (pLockedVolume->SlicePitch * pBox->Front) + /* FIXME: is front < back or vica versa? */ + (pLockedVolume->RowPitch * pBox->Top) + + (pBox->Left * This->bytesPerPixel); + } + TRACE("returning pBits=%p, rpitch=%d, spitch=%d\n", pLockedVolume->pBits, pLockedVolume->RowPitch, pLockedVolume->SlicePitch); + return D3D_OK; + + + + return D3D_OK; } HRESULT WINAPI IDirect3DVolume8Impl_UnlockBox(LPDIRECT3DVOLUME8 iface) { ICOM_THIS(IDirect3DVolume8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + TRACE("(%p) : stub\n", This); + if (This->Container) { + IDirect3DVolumeTexture8 *cont = This->Container; + + int containerType = IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) cont); + if (containerType == D3DRTYPE_VOLUMETEXTURE) { + IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)cont; + pTexture->Dirty = TRUE; + } else { + FIXME("Set dirty on container type %d\n", containerType); + } + } + return D3D_OK; } diff --git a/dlls/d3d8/volumetexture.c b/dlls/d3d8/volumetexture.c index c94d7bb5d34..9f4f2e2d4b4 100644 --- a/dlls/d3d8/volumetexture.c +++ b/dlls/d3d8/volumetexture.c @@ -55,9 +55,18 @@ ULONG WINAPI IDirect3DVolumeTexture8Impl_AddRef(LPDIRECT3DVOLUMETEXTURE8 iface) ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8 iface) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); ULONG ref = --This->ref; + int i; + TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) + if (ref == 0) { + for (i=0; ilevels; i++) { + if (This->volumes[i] != NULL) { + TRACE("(%p) : Releasing volume %p\n", This, This->volumes[i]); + IDirect3DVolume8Impl_Release((LPDIRECT3DVOLUME8) This->volumes[i]); + } + } HeapFree(GetProcessHeap(), 0, This); + } return ref; } @@ -109,28 +118,47 @@ DWORD WINAPI IDirect3DVolumeTexture8Impl_GetLOD(LPDIRECT3DVOLUMETEXTUR } DWORD WINAPI IDirect3DVolumeTexture8Impl_GetLevelCount(LPDIRECT3DVOLUMETEXTURE8 iface) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + TRACE("(%p) : returning %d\n", This, This->levels); + return This->levels; } /* IDirect3DVolumeTexture8 */ HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetLevelDesc(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level,D3DVOLUME_DESC *pDesc) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + if (Level < This->levels) { + TRACE("(%p) Level (%d)\n", This, Level); + return IDirect3DVolume8Impl_GetDesc((LPDIRECT3DVOLUME8)This->volumes[Level], pDesc); + } else { + FIXME("(%p) Level (%d)\n", This, Level); + } + return D3D_OK; } HRESULT WINAPI IDirect3DVolumeTexture8Impl_GetVolumeLevel(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level,IDirect3DVolume8** ppVolumeLevel) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + IDirect3DVolume8Impl_AddRef((LPDIRECT3DVOLUME8)This->volumes[Level]); + *ppVolumeLevel = (LPDIRECT3DVOLUME8)This->volumes[Level]; + TRACE("(%p) : returning %p for level %d\n", This, *ppVolumeLevel, Level); + return D3D_OK; } HRESULT WINAPI IDirect3DVolumeTexture8Impl_LockBox(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + TRACE("(%p) Level (%d)\n", This, Level); + if (Level < This->levels) { + return IDirect3DVolume8Impl_LockBox((LPDIRECT3DVOLUME8)This->volumes[Level], pLockedVolume, pBox, Flags); + } else { + FIXME("Volume Levels seems too high?!!\n"); + } + return D3D_OK; } HRESULT WINAPI IDirect3DVolumeTexture8Impl_UnlockBox(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); - FIXME("(%p) : stub\n", This); return D3D_OK; + This->Dirty = TRUE; + TRACE("(%p) : stub\n", This); + return D3D_OK; } HRESULT WINAPI IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3DVOLUMETEXTURE8 iface, CONST D3DBOX* pDirtyBox) { ICOM_THIS(IDirect3DVolumeTexture8Impl,iface); + This->Dirty = TRUE; FIXME("(%p) : stub\n", This); return D3D_OK; }