You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
15 KiB
406 lines
15 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: haltex.c
|
|
* Content: Direct3D HAL texture handling
|
|
*@@BEGIN_MSINTERNAL
|
|
*
|
|
* $Id: haltex.c,v 1.1 1995/11/21 15:12:43 sjl Exp $
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 07/11/95 stevela Initial rev.
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* Texture functionality is not emulated.
|
|
*/
|
|
|
|
HRESULT D3DHAL_TextureCreate(LPDIRECT3DDEVICEI lpDevI,
|
|
LPD3DTEXTUREHANDLE lphTex,
|
|
LPDIRECTDRAWSURFACE lpDDS)
|
|
{
|
|
if (IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
*lphTex =
|
|
((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
}
|
|
else
|
|
{
|
|
D3DHAL_TEXTURECREATEDATA data;
|
|
HRESULT ret;
|
|
|
|
if (!lpDevI->lpD3DHALCallbacks->TextureCreate) {
|
|
D3D_ERR("TextureCreate called, but no texture support.");
|
|
return (D3DERR_TEXTURE_NO_SUPPORT);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(D3DHAL_TEXTURECREATEDATA));
|
|
data.dwhContext = lpDevI->dwhContext;
|
|
data.lpDDS = lpDDS;
|
|
|
|
D3D_INFO(6, "TextureCreate, creating texture dwhContext = %08lx, lpDDS = %08lx",
|
|
data.dwhContext, data.lpDDS);
|
|
|
|
CALL_HALONLY(ret, lpDevI, TextureCreate, &data);
|
|
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
|
|
D3D_ERR("HAL failed to handle TextureCreate");
|
|
return (D3DERR_TEXTURE_CREATE_FAILED);
|
|
}
|
|
*lphTex = data.dwHandle;
|
|
}
|
|
|
|
D3D_INFO(6, "TextureCreate, created texture hTex = %08lx", *lphTex);
|
|
return (D3D_OK);
|
|
}
|
|
|
|
HRESULT D3DHAL_TextureDestroy(LPD3DI_TEXTUREBLOCK lpBlock)
|
|
{
|
|
LPDIRECT3DDEVICEI lpDevI=lpBlock->lpDevI;
|
|
D3DTEXTUREHANDLE hTex=lpBlock->hTex;
|
|
D3DHAL_TEXTUREDESTROYDATA data;
|
|
HRESULT ret;
|
|
lpBlock->hTex=0;
|
|
if (!IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
// on winnt we alway use the surfacehandle, so there is no need calling driver
|
|
if (!lpDevI->lpD3DHALCallbacks->TextureDestroy) {
|
|
D3D_ERR("TextureDestroy called, but no texture support.");
|
|
return (D3DERR_TEXTURE_NO_SUPPORT);
|
|
}
|
|
}
|
|
// The following code ensures that before we ask the driver to unmap
|
|
// the texture, we set the stages to NULL if the texture is still present
|
|
// in any stage. This is probably not necessary, but we are just trying
|
|
// to be extra cautious here. The CAVEAT here is that it is possible that
|
|
// D3DHAL_TextureDestroy() is being called from DestroyDevice() and hence
|
|
// IT COULD BE REALLY BAD TO BATCH additional commands to the device at
|
|
// this stage. (snene - 3/2/98)
|
|
BOOL bNeedFlush = FALSE;
|
|
if (IS_DP2HAL_DEVICE(lpDevI)) {
|
|
int dwStage;
|
|
CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2 *>(lpDevI);
|
|
|
|
// Find out the first stage with hTex and NULL out
|
|
for (dwStage=0;dwStage<(int)lpDevI->dwMaxTextureBlendStages; dwStage++)
|
|
{
|
|
if (hTex == lpDevI->tsstates[dwStage][D3DTSS_TEXTUREMAP])
|
|
{
|
|
dp2dev->SetTSSI(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, 0);
|
|
bNeedFlush = TRUE;
|
|
}
|
|
}
|
|
}
|
|
DWORD txh;
|
|
if(lpDevI->GetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, &txh) != D3D_OK)
|
|
{
|
|
D3D_WARN(0, "Error getting texture handle in D3DHAL_TextureDestroy");
|
|
}
|
|
else
|
|
{
|
|
if (txh == hTex)
|
|
{
|
|
lpDevI->rstates[D3DRENDERSTATE_TEXTUREHANDLE] = 0;
|
|
lpDevI->SetRenderStateI(D3DRENDERSTATE_TEXTUREHANDLE, 0);
|
|
bNeedFlush = TRUE;
|
|
}
|
|
}
|
|
|
|
// Make sure that we send down the command immediately to guarantee
|
|
// that the driver gets it before we call it with Destroy
|
|
if(bNeedFlush)
|
|
{
|
|
if(lpDevI->FlushStates() != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in D3DHAL_TextureDestroy");
|
|
}
|
|
}
|
|
else // Now we decide whether to flush due to a referenced texture in the batch or not
|
|
{
|
|
LPD3DBUCKET list;
|
|
if(lpBlock->lpD3DTextureI->lpDDS != NULL)
|
|
{
|
|
list = reinterpret_cast<LPD3DBUCKET>(((LPDDRAWI_DDRAWSURFACE_INT)(lpBlock->lpD3DTextureI->lpDDS))->lpLcl->lpSurfMore->lpD3DDevIList);
|
|
}
|
|
else
|
|
{
|
|
list = reinterpret_cast<LPD3DBUCKET>(((LPDDRAWI_DDRAWSURFACE_INT)(lpBlock->lpD3DTextureI->lpDDSSys))->lpLcl->lpSurfMore->lpD3DDevIList);
|
|
}
|
|
while(list != NULL)
|
|
{
|
|
if(list->lpD3DDevI == lpDevI)
|
|
{
|
|
if(lpDevI->FlushStates() != D3D_OK)
|
|
{
|
|
D3D_ERR("Error trying to render batched commands in D3DHAL_TextureDestroy");
|
|
}
|
|
break;
|
|
}
|
|
list = list->next;
|
|
}
|
|
}
|
|
if (!IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
memset(&data, 0, sizeof(D3DHAL_TEXTUREDESTROYDATA));
|
|
data.dwhContext = lpDevI->dwhContext;
|
|
data.dwHandle = hTex;
|
|
|
|
D3D_INFO(6, "TextureDestroy, destroying texture dwhContext = %08lx, hTex = %08lx",
|
|
data.dwhContext, hTex);
|
|
|
|
CALL_HALONLY(ret, lpDevI, TextureDestroy, &data);
|
|
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
|
|
D3D_ERR("HAL failed to handle TextureDestroy");
|
|
return (D3DERR_TEXTURE_DESTROY_FAILED);
|
|
}
|
|
}
|
|
D3D_INFO(6, "TextureDestroy, destroyed texture hTex = %08lx", hTex);
|
|
return (D3D_OK);
|
|
}
|
|
|
|
HRESULT D3DHAL_TextureSwap(LPDIRECT3DDEVICEI lpDevI,
|
|
D3DTEXTUREHANDLE hTex1,
|
|
D3DTEXTUREHANDLE hTex2)
|
|
{
|
|
D3DHAL_TEXTURESWAPDATA data;
|
|
HRESULT ret;
|
|
|
|
if (!lpDevI->lpD3DHALCallbacks->TextureSwap) {
|
|
D3D_ERR("TextureSwapcalled, but no texture support.");
|
|
return (D3DERR_TEXTURE_NO_SUPPORT);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(D3DHAL_TEXTURESWAPDATA));
|
|
data.dwhContext = lpDevI->dwhContext;
|
|
data.dwHandle1 = hTex1;
|
|
data.dwHandle2 = hTex2;
|
|
data.ddrval = D3D_OK;
|
|
D3D_INFO(6, "TextureSwap, dwhContext = %d. hTex1 = %d, hTex2 = %d",
|
|
data.dwhContext, hTex1, hTex2);
|
|
CALL_HALONLY(ret, lpDevI, TextureSwap, &data);
|
|
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
|
|
D3D_ERR("HAL failed to handle TextureSwap");
|
|
return (D3DERR_TEXTURE_SWAP_FAILED);
|
|
}
|
|
return (D3D_OK);
|
|
}
|
|
|
|
__declspec (dllexport) HRESULT
|
|
D3DHAL_TextureGetSurf(LPDIRECT3DDEVICEI lpDevI,
|
|
D3DTEXTUREHANDLE hTex,
|
|
LPDIRECTDRAWSURFACE* lpDDS)
|
|
{
|
|
if (IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
LPD3DI_TEXTUREBLOCK tBlock=LIST_FIRST(&lpDevI->texBlocks);
|
|
while (tBlock)
|
|
{
|
|
if (tBlock->hTex == hTex)
|
|
{
|
|
*lpDDS = (LPDIRECTDRAWSURFACE)tBlock->lpD3DTextureI->lpDDS1Tex;
|
|
return D3D_OK;
|
|
}
|
|
tBlock=LIST_NEXT(tBlock,devList);
|
|
}
|
|
return (D3DERR_TEXTURE_CREATE_FAILED);
|
|
}
|
|
else
|
|
{
|
|
D3DHAL_TEXTUREGETSURFDATA data;
|
|
HRESULT ret;
|
|
|
|
if (!lpDevI->lpD3DHALCallbacks->TextureGetSurf) {
|
|
D3D_ERR("TextureGetSurf called, but no texture support.");
|
|
return (D3DERR_TEXTURE_NO_SUPPORT);
|
|
}
|
|
|
|
memset(&data, 0, sizeof(D3DHAL_TEXTUREGETSURFDATA));
|
|
data.dwhContext = lpDevI->dwhContext;
|
|
data.dwHandle = hTex;
|
|
|
|
D3D_INFO(6, "TextureGetSurf, getting texture for dwhContext = %d, hTex = %d",
|
|
data.dwhContext, hTex);
|
|
|
|
CALL_HALONLY(ret, lpDevI, TextureGetSurf, &data);
|
|
if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
|
|
D3D_ERR("HAL failed to handle TextureGetSurf");
|
|
return (D3DERR_TEXTURE_CREATE_FAILED);
|
|
}
|
|
|
|
*lpDDS = (LPDIRECTDRAWSURFACE)data.lpDDS;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
}
|
|
|
|
HRESULT D3DHELInst_D3DOP_TEXTURELOAD(LPDIRECT3DDEVICEI lpDevI,
|
|
DWORD dwCount,
|
|
LPD3DTEXTURELOAD load)
|
|
{
|
|
HRESULT ddrval;
|
|
DWORD i;
|
|
LPDIRECTDRAWSURFACE lpDDSSrc;
|
|
LPDIRECTDRAWSURFACE lpDDSDst;
|
|
DDSURFACEDESC ddsd;
|
|
PALETTEENTRY ppe[256];
|
|
LPDIRECTDRAWPALETTE lpDDPalSrc, lpDDPalDst;
|
|
int psize;
|
|
|
|
for (i = 0; i < dwCount; i++) {
|
|
if (D3DHAL_TextureGetSurf(lpDevI, load->hSrcTexture, &lpDDSSrc)) {
|
|
D3D_ERR("HAL failed to get source surface in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
if (D3DHAL_TextureGetSurf(lpDevI, load->hDestTexture, &lpDDSDst)) {
|
|
D3D_ERR("HAL failed to get destination surface in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
|
|
memset(&ddsd, 0, sizeof ddsd);
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddrval = lpDDSDst->GetSurfaceDesc(&ddsd);
|
|
if (ddrval != DD_OK) {
|
|
D3D_ERR("Failed to get surface description of source texture surface in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
|
|
if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
|
|
psize = 256;
|
|
} else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
|
|
psize = 16;
|
|
} else {
|
|
psize = 0;
|
|
}
|
|
|
|
if (psize) {
|
|
ddrval = lpDDSSrc->GetPalette(&lpDDPalSrc);
|
|
if (ddrval != DD_OK) {
|
|
if (ddrval != DDERR_NOPALETTEATTACHED) {
|
|
D3D_ERR("Failed to get palette of source texture in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
} else {
|
|
ddrval = lpDDPalSrc->GetEntries(0, 0, psize, ppe);
|
|
if (ddrval != DD_OK) {
|
|
D3D_ERR("Failed to get palette entries of source texture in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
lpDDPalSrc->Release();
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
lpDDPalSrc->Release();
|
|
ddrval = lpDDSDst->GetPalette(&lpDDPalDst);
|
|
if (ddrval != DD_OK) {
|
|
D3D_ERR("Failed to get palette of destination texture in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
ddrval = lpDDPalDst->SetEntries(0, 0, psize, ppe);
|
|
if (ddrval != DD_OK) {
|
|
D3D_ERR("Failed to set palette entries of destination texture in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
lpDDPalDst->Release();
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
lpDDPalDst->Release();
|
|
}
|
|
}
|
|
|
|
lpDDSSrc->AddRef();
|
|
lpDDSDst->AddRef();
|
|
do {
|
|
DDSCAPS ddscaps;
|
|
LPDIRECTDRAWSURFACE lpDDSTmp;
|
|
ddrval = lpDDSDst->Blt(NULL, lpDDSSrc,
|
|
NULL, DDBLT_WAIT, NULL);
|
|
|
|
if (ddrval == E_NOTIMPL && (psize == 16 || psize == 4 || psize == 2) ) {
|
|
DDSURFACEDESC ddsd_s, ddsd_d;
|
|
LPBYTE psrc, pdst;
|
|
DWORD i;
|
|
DWORD dwBytesPerLine;
|
|
|
|
memset(&ddsd_s, 0, sizeof ddsd_s);
|
|
memset(&ddsd_d, 0, sizeof ddsd_d);
|
|
ddsd_s.dwSize = ddsd_d.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
if ((ddrval = lpDDSSrc->Lock(NULL, &ddsd_s, DDLOCK_WAIT, NULL)) != DD_OK) {
|
|
lpDDSSrc->Release();
|
|
lpDDSDst->Release();
|
|
D3D_ERR("Failed to lock src surface");
|
|
return ddrval;
|
|
}
|
|
if ((ddrval = lpDDSDst->Lock(NULL, &ddsd_d, DDLOCK_WAIT, NULL)) != DD_OK) {
|
|
lpDDSSrc->Unlock(NULL);
|
|
lpDDSSrc->Release();
|
|
lpDDSDst->Release();
|
|
D3D_ERR("Failed to lock dst surface");
|
|
return ddrval;
|
|
}
|
|
|
|
switch (psize)
|
|
{
|
|
case 16: dwBytesPerLine = (ddsd.dwWidth + 1) / 2; break;
|
|
case 4: dwBytesPerLine = (ddsd.dwWidth + 3) / 4; break;
|
|
case 2: dwBytesPerLine = (ddsd.dwWidth + 7) / 8; break;
|
|
}
|
|
|
|
psrc = (LPBYTE)ddsd_s.lpSurface;
|
|
pdst = (LPBYTE)ddsd_d.lpSurface;
|
|
for (i = 0; i < ddsd_s.dwHeight; i++) {
|
|
memcpy( pdst, psrc, dwBytesPerLine );
|
|
psrc += ddsd_s.lPitch;
|
|
pdst += ddsd_d.lPitch;
|
|
}
|
|
|
|
lpDDSSrc->Unlock(NULL);
|
|
lpDDSDst->Unlock(NULL);
|
|
lpDDSSrc->Release();
|
|
lpDDSDst->Release();
|
|
return D3D_OK;
|
|
|
|
}
|
|
if (ddrval != DD_OK)
|
|
{
|
|
lpDDSSrc->Release();
|
|
lpDDSDst->Release();
|
|
return ddrval;
|
|
}
|
|
|
|
memset(&ddscaps, 0, sizeof(DDSCAPS));
|
|
ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
|
|
ddrval = lpDDSSrc->GetAttachedSurface(&ddscaps, &lpDDSTmp);
|
|
lpDDSSrc->Release();
|
|
lpDDSSrc = lpDDSTmp;
|
|
if (ddrval == DDERR_NOTFOUND) {
|
|
// no more surfaces in the chain
|
|
lpDDSDst->Release();
|
|
break;
|
|
} else if (ddrval != DD_OK) {
|
|
lpDDSDst->Release();
|
|
D3D_ERR("GetAttachedSurface of source failed in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
memset(&ddscaps, 0, sizeof(DDSCAPS));
|
|
ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
|
|
ddrval = lpDDSDst->GetAttachedSurface(&ddscaps, &lpDDSTmp);
|
|
lpDDSDst->Release();
|
|
lpDDSDst = lpDDSTmp;
|
|
if (ddrval == DDERR_NOTFOUND) {
|
|
lpDDSSrc->Release();
|
|
D3D_ERR("Destination texture has fewer attached mipmap surfaces than source in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
} else if (ddrval != DD_OK) {
|
|
lpDDSSrc->Release();
|
|
D3D_ERR("GetAttachedSurface of destination failed in D3DHELInst_D3DOP_TEXTURELOAD");
|
|
return (D3DERR_TEXTURE_LOAD_FAILED);
|
|
}
|
|
} while (1);
|
|
load++;
|
|
}
|
|
return (D3D_OK);
|
|
}
|
|
|