Leaked source code of windows server 2003
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

/*==========================================================================;
*
* 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);
}