📄 texture.c
字号:
/*
* Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
*
* File: texture.c
*
* Loads and manages textures. Part of D3DApp.
*
* D3DApp is a collection of helper functions for Direct3D applications.
* D3DApp consists of the following files:
* d3dapp.h Main D3DApp header to be included by application
* d3dappi.h Internal header
* d3dapp.c D3DApp functions seen by application.
* ddcalls.c All calls to DirectDraw objects except textures
* d3dcalls.c All calls to Direct3D objects except textures
* texture.c Texture loading and managing texture list
* misc.c Miscellaneous calls
*/
#include "d3dappi.h"
#define MAGICBYTES 2
/*
* STATIC FUNCTION DECLARATIONS
*/
static void D3DAppIAddPathList(const char *path);
static void D3DAppIInitialisePathList();
static FILE * D3DAppIFindFile(const char *name, const char *mode);
static BOOL loadPPMHeader(FILE *fp, DWORD *width, DWORD *height, int *maxgrey);
/***************************************************************************/
/* Managing the texture list */
/***************************************************************************/
/*
* D3DAppILoadTextureSurf
* Creates a texture map surface and texture object from the numbered PPM
* file. This is done in a two step process. A source texture surface and
* object are created in system memory. A second, initially empty, texture
* surface is created (in video memory if hardware is present). The source
* texture is loaded into the destination texture surface and then discarded.
* This process allows a device to compress or reformat a texture map as it
* enters video memory during the Load call.
*/
BOOL
D3DAppILoadTextureSurf(int n, BOOL* bInVideo)
{
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE lpSrcTextureSurf = NULL;
LPDIRECT3DTEXTURE lpSrcTexture = NULL;
LPDIRECTDRAWPALETTE lpDstPalette = NULL;
PALETTEENTRY ppe[256];
DWORD pcaps;
/*
* Release the surface if it is hanging around
*/
RELEASE(d3dappi.lpTextureSurf[n]);
/*
* Create a surface in system memory and load the PPM file into it.
* Query for the texture interface.
*/
lpSrcTextureSurf = D3DAppILoadSurface(d3dappi.lpDD, d3dappi.ImageFile[n],
&d3dappi.ThisTextureFormat.ddsd,
DDSCAPS_SYSTEMMEMORY);
if (!lpSrcTextureSurf)
goto exit_with_error;
LastError = lpSrcTextureSurf->lpVtbl->QueryInterface(lpSrcTextureSurf,
&IID_IDirect3DTexture,
(LPVOID*)&lpSrcTexture);
if (LastError != DD_OK) {
D3DAppISetErrorString("Failed to obtain D3D texture interface for a source texture.\n%s", D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* Create an empty texture surface to load the source texture into.
* The DDSCAPS_ALLOCONLOAD flag allows the DD driver to wait until the
* load call to allocate the texture in memory because at this point,
* we may not know how much memory the texture will take up (e.g. it
* could be compressed to an unknown size in video memory).
* Make sure SW renderers get textures in system memory
*/
LastError = D3DAppIGetSurfDesc(&ddsd, lpSrcTextureSurf);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not get the surface description of the source texture.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD;
if (!d3dappi.ThisDriver.bIsHardware)
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
LastError = D3DAppICreateSurface(&ddsd, &d3dappi.lpTextureSurf[n]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not create the destination texture surface.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
} else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
pcaps = DDPCAPS_4BIT;
} else {
pcaps = 0;
}
if (pcaps) {
memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
LastError = d3dappi.lpDD->lpVtbl->CreatePalette(d3dappi.lpDD, pcaps,
ppe, &lpDstPalette, NULL);
if (LastError != DD_OK) {
D3DAppISetErrorString("Failed to create a palette for the destination texture.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
LastError = d3dappi.lpTextureSurf[n]->lpVtbl->SetPalette(d3dappi.lpTextureSurf[n],
lpDstPalette);
if (LastError != DD_OK) {
D3DAppISetErrorString("Failed to set the destination texture's palette.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
// lpDstPalette->lpVtbl->Release(lpDstPalette);
}
/*
* Query our destination surface for a texture interface
*/
LastError = d3dappi.lpTextureSurf[n]->lpVtbl->QueryInterface(d3dappi.lpTextureSurf[n],
&IID_IDirect3DTexture,
(LPVOID*)&d3dappi.lpTexture[n]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Failed to obtain D3D texture interface for a destination texture.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* Load the source texture into the destination. During this call, a
* driver could compress or reformat the texture surface and put it in
* video memory.
*/
LastError = d3dappi.lpTexture[n]->lpVtbl->Load(d3dappi.lpTexture[n], lpSrcTexture);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not load a source texture into a destination texture.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* Now we are done with the source texture
*/
RELEASE(lpSrcTexture);
RELEASE(lpSrcTextureSurf);
/*
* Did the texture end up in video memory?
*/
LastError = D3DAppIGetSurfDesc(&ddsd, d3dappi.lpTextureSurf[n]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not get the surface description of the loaded texture surface.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
*bInVideo = TRUE;
else
*bInVideo = FALSE;
return TRUE;
exit_with_error:
RELEASE(lpSrcTexture);
RELEASE(lpSrcTextureSurf);
RELEASE(lpDstPalette);
RELEASE(d3dappi.lpTexture[n]);
RELEASE(d3dappi.lpTextureSurf[n]);
return FALSE;
}
// create a texture for the spot polygon in the HW scene
#include "main.h"
void Msg(LPSTR message, HRESULT ddrval);
BOOL createSwTexture()
{
HRESULT ddrval;
DDSURFACEDESC ddsd;
char *error_str;
if (!d3dappi.ThisDriver.bIsHardware) {
Msg("No HW present, Mixed Rendering doesn't help !!! ", ddrval);
return FALSE;
}
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
d3dappi.lpBackBuffer->lpVtbl->GetSurfaceDesc(d3dappi.lpBackBuffer, &ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ALLOCONLOAD;
ddsd.dwHeight = 256;
ddsd.dwWidth = 256;
#if 0 // these will already be set by GetSurfaceDesc
/* mark the pixel format */
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB ;
ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
#endif
ddrval = d3dappi.lpDD->lpVtbl->CreateSurface(
d3dappi.lpDD, &ddsd, &lpDDTextureSurfaceSPOT, NULL);
if (ddrval != DD_OK) {
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
Msg("texture.c : CreateSurface for texture failed (loadtex).\0", ddrval);
return(FALSE);
}
ddrval = lpDDTextureSurfaceSPOT->lpVtbl->QueryInterface(
lpDDTextureSurfaceSPOT, &IID_IDirect3DTexture, (LPVOID*)&lpSPOTTexture);
if (ddrval != DD_OK) {
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
Msg("texture.c: Failed to obtain texture interface for software texture.\0", ddrval);
return(FALSE);
}
ddrval = lpSPOTTexture->lpVtbl->GetHandle(lpSPOTTexture,
d3dappi.lpD3DDevice, &SPOTTextureHandle);
if (ddrval != D3D_OK) {
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
Msg("texture.c: Failed to obtain texture handle for the software texture.\0", ddrval);
return(FALSE);
}
return TRUE;
}
/*
Load Texture surface from the SW buffer of the previous frame (OG)
We load by memcpy from system memory to video memory
*/
BOOL
LoadTextureFromSW()
{
HRESULT ddrval;
char *error_str;
ddrval = lpDDActiveSurfaceSystem->lpVtbl->QueryInterface(lpDDActiveSurfaceSystem,
&IID_IDirect3DTexture, (LPVOID*)&lpActiveTexture);
if (ddrval != DD_OK) {
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
Msg("Failed to obtain D3D texture interface for a source texture.\0", ddrval);
return FALSE;
}
ddrval = lpSPOTTexture->lpVtbl->Load(lpSPOTTexture, lpActiveTexture);
if (ddrval != DD_OK) {
D3DAppISetErrorString("Could not load a source SW texture into a destination HW texture.\n%s",
D3DAppErrorToString(ddrval));
return FALSE ;
}
return TRUE;
}
/*
* D3DAppIReloadTextureSurf
* Reloads a lost and restored texture surface
*/
BOOL
D3DAppIReloadTextureSurf(int n)
{
LPDIRECTDRAWSURFACE lpSrcTextureSurf = NULL;
LPDIRECT3DTEXTURE lpSrcTexture = NULL;
/*
* Create a surface in system memory and load the PPM file into it.
* Query for the texture interface.
*/
lpSrcTextureSurf = D3DAppILoadSurface(d3dappi.lpDD, d3dappi.ImageFile[n],
&d3dappi.ThisTextureFormat.ddsd,
DDSCAPS_SYSTEMMEMORY);
if (!lpSrcTextureSurf)
goto exit_with_error;
LastError = lpSrcTextureSurf->lpVtbl->QueryInterface(lpSrcTextureSurf,
&IID_IDirect3DTexture,
(LPVOID*)&lpSrcTexture);
if (LastError != DD_OK) {
D3DAppISetErrorString("Failed to obtain D3D texture interface for a source texture.\n%s", D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* Load the source texture into the destination. During this call, a
* driver could compress or reformat the texture surface and put it in
* video memory.
*/
LastError = d3dappi.lpTexture[n]->lpVtbl->Load(d3dappi.lpTexture[n], lpSrcTexture);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not load a source texture into a destination texture.\n%s",
D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* Now we are done with the source texture
*/
RELEASE(lpSrcTexture);
RELEASE(lpSrcTextureSurf);
return TRUE;
exit_with_error:
RELEASE(lpSrcTexture);
RELEASE(lpSrcTextureSurf);
return FALSE;
}
/*
* D3DAppIGetTextureHandle
* Get a texture handle from the current D3D device for this texture and save
* it in the MasterTextureHandle list and public texture handle list.
*/
BOOL
D3DAppIGetTextureHandle(int n)
{
LastError = d3dappi.lpTexture[n]->lpVtbl->GetHandle(d3dappi.lpTexture[n],
d3dappi.lpD3DDevice, &MasterTextureHandle[n]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Could not get a handle to loaded texture %i.\n%s",
n, D3DAppErrorToString(LastError));
goto exit_with_error;
}
/*
* If textures are enabled, put the handle in the public texture list,
* otherwise, keep it as zero.
*/
if (!d3dappi.bTexturesDisabled) {
d3dappi.TextureHandle[n] = MasterTextureHandle[n];
} else {
d3dappi.TextureHandle[n] = 0;
}
return TRUE;
exit_with_error:
MasterTextureHandle[n] = 0;
d3dappi.TextureHandle[n] = 0;
return FALSE;
}
/*
* D3DAppIReleaseTexture
* Release this texture surface and texture interface. Remember, a texture
* handle is NOT and object and does not need to be released or destroyed.
* The handle is no longer valid after the device is destroyed, so set it to
* zero here.
*/
void
D3DAppIReleaseTexture(int n)
{
RELEASE(d3dappi.lpTexture[n]);
RELEASE(d3dappi.lpTextureSurf[n]);
MasterTextureHandle[n] = 0;
d3dappi.TextureHandle[n] = 0;
}
/*
* D3DAppIReleaseAllTextures
* Release all texture surfaces and texture interfaces
*/
void
D3DAppIReleaseAllTextures(void)
{
int i;
for (i = 0; i < d3dappi.NumTextures; i++) {
D3DAppIReleaseTexture(i);
}
}
/*
* D3DAppILoadAllTextures
* Load all texture surfaces, qeury them for texture interfaces and get
* handles for them from the current D3D driver.
*/
BOOL
D3DAppILoadAllTextures(void)
{
int i;
if (d3dappi.ThisDriver.bDoesTextures) {
d3dappi.NumUsableTextures = 0;
for (i = 0; i < d3dappi.NumTextures; i++) {
BOOL bInVideo;
ATTEMPT(D3DAppILoadTextureSurf(i, &bInVideo));
if (!bInVideo && d3dappi.ThisDriver.bIsHardware) {
/*
* If a texture fails to load into video memory for a hardware
* device, stop the NumUsableTextures count here.
*/
D3DAppIReleaseTexture(i);
break;
} else {
++d3dappi.NumUsableTextures;
}
}
for (i = 0; i < d3dappi.NumUsableTextures; i++) {
ATTEMPT(D3DAppIGetTextureHandle(i));
}
} else {
d3dappi.NumUsableTextures = 0;
}
return TRUE;
exit_with_error:
for (i = 0; i < d3dappi.NumTextures; i++) {
D3DAppIReleaseTexture(i);
}
return FALSE;
}
/***************************************************************************/
/* Loading a PPM file into a surface */
/***************************************************************************/
/*
* LoadSurface
* Loads a ppm file into a texture map DD surface of the given format. The
* memory flag specifies DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY.
*/
LPDIRECTDRAWSURFACE
D3DAppILoadSurface(LPDIRECTDRAW lpDD, LPCSTR lpName,
LPDDSURFACEDESC lpFormat, DWORD memoryflag)
{
LPDIRECTDRAWSURFACE lpDDS;
DDSURFACEDESC ddsd, format;
D3DCOLOR colors[256];
D3DCOLOR c;
DWORD dwWidth, dwHeight;
int i, j;
FILE *fp;
char *lpC;
LPDIRECTDRAWPALETTE lpDDPal;
PALETTEENTRY ppe[256];
int psize;
DWORD pcaps;
int color_count;
BOOL bQuant = FALSE;
HRESULT ddrval;
/*
* Find the image file and open it
*/
fp = D3DAppIFindFile(lpName, "rb");
if (fp == NULL) {
D3DAppISetErrorString("Cannot find %s.\n", lpName);
return NULL;
}
/*
* Parse the PPM header
*/
if (!loadPPMHeader(fp, &dwWidth, &dwHeight, &i)) {
fclose(fp);
D3DAppISetErrorString("Could not load or parse PPM header in %s.\n", lpName);
return NULL;
}
/*
* Create a surface of the given format using the dimensions of the PPM
* file.
*/
memcpy(&format, lpFormat, sizeof(DDSURFACEDESC));
if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
bQuant = TRUE;
psize = 256;
pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
} else if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
bQuant = TRUE;
psize = 16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -